Summary

Section 21.1 Introduction

  • The prepackaged data-structure classes provided by the .NET Framework are known as collection classes—they store collections of data.

  • With collection classes, instead of creating data structures to store these sets of items, you simply use existing data structures, without concern for how they’re implemented.

Section 21.2 Collections Overview

  • The .NET Framework collections provide high-performance, high-quality implementations of common data structures and enable effective software reuse.

  • In earlier versions of C#, the .NET Framework primarily provided the collection classes in the System.Collections namespace to store and manipulate object references.

  • The .NET Framework’s System.Collections.Generic namespace contains collection classes that take advantage of .NET’s generics capabilities.

Section 21.3 Class Array and Enumerators

  • All arrays implicitly inherit from abstract base class Array (namespace System).

Section 21.3.1 C# 6 using static Directive

  • C# 6’s using static directive allows access to a class’s static members without fully qualifying their names.

Section 21.3.3 Array Method Sort

  • The static Array method Sort sorts an array.

Section 21.3.4 Array Method Copy

  • The static Array method Copy copies elements from one array to another.

Section 21.3.5 Array Method BinarySearch

  • The static Array method BinarySearch performs binary searches on an array. This method assumes that it receives a sorted array.

Section 21.3.6 Array Method GetEnumerator and Interface IEnumerator

  • A collection’s GetEnumerator method returns an enumerator that can iterate over the collection.

  • All enumerators have methods MoveNext and Reset and property Current.

  • MoveNext moves the enumerator to the next element in the collection. MoveNext returns true if there’s at least one more element in the collection; otherwise, the method returns false.

  • Read-only property Current returns the object at the current location in the collection.

Section 21.3.7 Iterating Over a Collection with foreach

  • The               foreach statement implicitly obtains an enumerator via the GetEnumerator method and uses the enumerator’s MoveNext method and Current property to traverse the collection. This can be done with any collection that implements the IEnumerable interface—not just arrays.

Section 21.3.8 Array Methods Clear, IndexOf, LastIndexOf and Reverse

  • The static Array method Clear sets a range of elements to 0, false or null, as appropriate.

  • The static Array method IndexOf locates the first occurrence of an object in an array or portion of an array.

  • The static Array method LastIndexOf locate the last occurrence of an object in an array or portion of an array.

  • The static Array method Reverse reverses the contents of an array or portion of an array.

Section 21.4 Dictionary Collections

  • A dictionary is a collection of key–value pairs. A hash table is one way to implement a dictionary.

Section 21.4.1 Dictionary Fundamentals

  • Hashing is a high-speed scheme for converting keys to unique array indices.

Section 21.4.2 Using the SortedDictionary Collection

  • Generic class SortedDictionary does not use a hash table, but instead stores its key–value pairs in a binary search tree.

  • Generic class SortedDictionary takes two type arguments—the first specifies the type of key and the second the type of value.

  • Method ContainsKey determines whether a key is in a dictionary.

  • SortedDictionary method Add creates a new entry in the dictionary, with the first argument as the key and the second as the value.

  • SortedDictionary’s indexer can be used to get or set a key’s corresponding value.

  • SortedDictionary property Keys gets an ICollection<T> that contains all the keys.

  • If you use a foreach statement with a SortedDictionary, the iteration variable is of type KeyValuePair, which has properties Key and Value for retrieving the current pair’s key and value.

  • Invoking the get accessor of a SortedDictionary indexer with a key that does not exist in the collection causes a KeyNotFoundException.

Section 21.5 Generic LinkedList Collection

  • The LinkedList class is a doubly linked list—we can navigate the list both backwards and forwards with nodes of generic class LinkedListNode.

  • Each node contains property Value and read-only properties Previous and Next.

  • The LinkedList class’s enumerator loops over the values of the nodes, not the nodes themselves.

  • One LinkedListNode cannot be a member of more than one LinkedList. Any attempt to add a node from one LinkedList to another generates an InvalidOperationException.

  • Method Find performs a linear search on the list and returns the first node that contains a value equal to the passed argument.

  • Method Remove deletes a node from a LinkedList.

Section 21.6 C# 6 Null Conditional Operator ?[]

  • C# 6 also provides a null-conditional operator, ?[], for arrays and for collections that support the [] indexing operator.

  • The ?[] operator determines whether the array or collection reference is null before accessing an element.

Section 21.7 C# 6 Dictionary Initializers and Collection Initializers

  • C# 6’s index initializer syntax enables you to initialize a Dictionary’s key–value pairs as in

    
    var variableName = new Dictionary<TypeOfKey, TypeOfValue>{
       [key1] = value1,
       [key2] = value2,
       [key3] = value3
    };
    

  • As of C# 6, the compiler also supports collection initializers for any collection that has an Add extension method.

Section 21.8 Delegates

  • A delegate is an object that holds a reference to a method.

  • Via delegates, you can assign methods to variables, and pass methods to and from other methods. You also can call methods through variables of delegate types.

  • The compiler converts LINQ queries into calls to extension methods—many of which have delegate parameters.

Section 21.8.1 Declaring a Delegate Type

  • A delegate type is declared by preceding a method header with keyword delegate (placed after any access specifiers, such as public or private) and following the method header with a semicolon.

  • A delegate type declaration includes the method header only—the header describes a set of methods with specific parameters and a specific return type.

Section 21.8.2 Declaring a Delegate Variable

  • A delegate variable can hold a reference to any method with a matching signature.

Section 21.8.3 Delegate Parameters

  • The real power of delegates is in passing method references as arguments to methods.

Section 21.8.4 Passing a Method Name Directly to a Delegate Parameter

  • A method name can be passed directly to a delegate parameter, rather than first assigning it to a delegate variable.

Section 21.9 Lambda Expressions

  • Lambda expressions allow you to define simple, anonymous methods—that is, methods that do not have names and that are defined where they are assigned to a delegate or passed to a delegate parameter.

  • Working with lambda expressions can reduce the size of your code and the complexity of working with delegates.

Section 21.9.1 Expression Lambdas

  • A lambda expression begins with a parameter list and is followed by the => lambda operator and an expression that represents the lambda’s body.

  • The value produced by the expression is implicitly returned by the lambda expression.

  • An expression lambda has a single expression to the right of the lambda operator.

  • A lambda’s return type is inferred from the return value or, in some cases, from a delegate’s return type.

Section 21.9.2 Assigning Lambdas to Delegate Variables

  • A delegate can hold a reference to a lambda expression that has a signature that’s compatible with the delegate type.

  • A lambda expression is called via a variable that references it.

Section 21.9.3 Explicitly Typed Lambda Parameters

  • Lambda expressions often are used as arguments to methods with delegate-type parameters, rather than defining and referencing a separate method or defining a delegate variable that references a lambda.

  • You can explicitly type a lambda expression’s parameters.

  • When specifying a lambda parameter’s type and/or when a lambda has more than one parameter, you must enclose the parameter list in parentheses.

Section 21.9.4 Statement Lambdas

  • A statement lambda contains a statement block—one or more statements enclosed in braces ({})—to the right of the lambda operator.

Section 21.10 Introduction to Functional Programming

  • With external iteration, you specify how to iterate, not the library. Also, you must access the elements sequentially from beginning to end in a single thread of execution.

  • External iteration requires variables that are mutated repeatedly as the iteration is performed.

  • External iteration is error prone.

  • In functional programming, you specify what you want to accomplish in a task, but not how to accomplish it.

  • You do not need to specify how to iterate through the elements or declare and use any mutable (that is, modifiable) variables. This is known as internal iteration, because the library code (behind the scenes) iterates through all the elements to perform the task.

  • A key aspect of functional programming is immutability—not modifying the data source being processed or any other program state, such as counter-control variables in loops. This eliminates common errors that are caused by modifying data incorrectly.

  • Three common functional-programming operations that you’ll perform on collections of data are filter, map and reduce.

  • A filter operation results in a new collection containing only the elements that satisfy a condition.

  • A map operation results in a new collection in which each element of the original collection is mapped to a new value (possibly of a different type). The new collection has the same number of elements as the collection that was mapped.

  • A reduce operation combines the elements of a collection into a single new value, typically using a lambda that specifies how to combine the elements.

  • Though C# was not originally designed as a functional-programming language, C#’s LINQ query syntax and LINQ extension methods support functional-programming techniques, such as internal iteration and immutability.

Section 21.11 Functional Programming with LINQ Method-Call Syntax and Lambdas

  • The same tasks you can perform with LINQ query syntax can also be performed with various LINQ extension methods and lambdas.

  • The compiler translates LINQ query syntax into calls to LINQ extension methods that receive lambdas as arguments.

Section 21.11.1 LINQ Extension Methods Min, Max, Sum and Average

  • Class Enumerable (namespace System.Linq) defines the LINQ to Objects extension methods.

  • Min returns the smallest value in the collection.

  • Max returns the largest value in the collection.

  • Sum returns the sum of all the values in the collection.

  • Average returns the average of all the values in the collection.

Section 21.11.2 Aggregate Extension Method for Reduction Operations

  • You can define your own reductions with the Aggregate LINQ extension method.

  • The version of Aggregate demonstrated in the chapter receives two arguments—a value that helps you begin the reduction operation and a Func delegate (namespace System) representing a method that receives two arguments and returns a value and specifies how to reduce the arguments. Once for each element in the collection, Aggregate calls this lambda expression.

  • On the first call to the lambda, Aggregate’s first argument and the first element of the collection are passed. Each subsequent call to the lambda uses the result of the previous call as the lambda’s first argument and the next element of the collection as the second. This continues until all elements of the collection have been processed to reduce the collection to a single value.

Section 21.11.3 The Where Extension Method for Filtering Operations

  • You filter elements to produce a collection of results that match a condition—known as a predicate.

  • LINQ extension method Where receives as its argument a Func delegate for a method that receives one argument and returns a bool indicating whether a given element should be included in the collection returned by Where.

  • The OrderBy extension method receives as its argument a Func delegate representing a method that receives one parameter (an element in the collection) and returns a value that’s used to order the results.

  • Calls to Where and OrderBy use deferred execution—they aren’t evaluated until you iterate over the results.

Section 21.11.4 Select Extension Method for Mapping Operations

  • Mapping transforms a collection’s elements to new values, which sometimes are of different types from the original elements.

  • LINQ extension method Select receives as its argument a Func delegate for a method that receives one argument (an element in the collection) and maps it to a new value (possibly of another type) that’s included in the collection returned by Select.

Section 21.12 PLINQ: Improving LINQ to Objects Performance with Multicore

  • A concept called threads enables the operating system to run parts of an app concurrently.

  • Though all of these tasks can make progress concurrently, they may do so by sharing one processor core.

  • With multicore processors, apps can operate truly in parallel on separate cores.

  • The operating system can allow one app’s threads to operate truly in parallel on separate cores, possibly increasing the app’s performance substantially.

  • Parallelizing apps and algorithms to take advantage of multiple cores is difficult and highly error prone, especially if those tasks share data that can be modified by one or more of the tasks.

  • Another benefit of functional programming is that you can easily ask the library to perform a task with parallel processing to take advantage of a processor’s multiple cores. This is the purpose of PLINQ (Parallel LINQ)—an implementation of the LINQ to Objects extension methods that parallelizes the operations for increased performance.

  • Class Enumerable provides static method Range to produce an IEnumerable<int> containing integer values in sequence. The first argument specifies the starting value in the range and the second specifies the number of values to produce.

  • Extension method ToArray returns an array representation of an IEnumerable<T>’s contents. Class Enumerable also provides method ToList to obtain a List<T> rather than an array.

  • DateTime’s Now property gets the current time.

  • DateTime method Subtract compute the difference between two DateTimes, which is returned as a TimeSpan.

  • TimeSpan’s TotalMilliseconds returns the number of milliseconds represented by the TimeSpan.

  • To initiate parallel processing, invoke IEnumerable<T> extension method AsParallel (from class ParallelEnumerable), which returns a ParallelQuery<T>.

  • An object that implements ParallelQuery<T> can be used with PLINQ’s parallelized versions of the LINQ extension methods.

  • Class ParallelEnumerable defines the ParallelQuery<T> (PLINQ) parallelized versions of LINQ to Objects extension methods as well as several PLINQ-specific extension methods.

Section 21.13 (Optional) Covariance and Contravariance for Generic Types

  • C# supports covariance and contravariance of generic interface and delegate types.

  • Assigning an array of a derived-class type to an array variable of a base-class type is an example of covariance.

  • Covariance now works with several generic interface types, including IEnumerable<T>.

  • Covariance in generic collections works only with reference types in the same class hierarchy.

  • Using a cast operator to assign an array variable of a base-class type to an array variable of a derived-class type is an example of contravariance.

  • Class SortedSet maintains a set of objects in sorted order—no duplicates are allowed.

  • The objects placed in a SortedSet must be comparable to determine their sorting order. Objects are comparable if their classes implement the IComparable<T> interface.

  • For classes that do not implement IComparable<T>, you can compare the objects using an object that implements the IComparer<T> interface. This interface’s Compare method compares its two arguments and returns 0 if they are equal, a negative integer if the first object is less than the second, or a positive integer if the first object is greater than the second.

  • Providing an IComparer for a base-class type where an IComparer for a derived-class type is expected is allowed because interface IComparer<T> supports contravariance.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset