221 Slices
Medium 9781449394011

Generics

Joseph Albahari O'Reilly Media ePub

C# has two separate mechanisms for writing code that is reusable across different types: inheritance and generics. Whereas inheritance expresses reusability with a base type, generics express reusability with a template that contains placeholder types. Generics, when compared to inheritance, can increase type safety and reduce casting and boxing.

A generic type declares type parametersplaceholder types to be filled in by the consumer of the generic type, which supplies the type arguments. Here is a generic type, Stack<T>, designed to stack instances of type T. Stack<T> declares a single type parameter T:

We can use Stack<T> as follows:

Notice that no downcasts are required in the last two lines, avoiding the possibility of runtime error and eliminating the overhead of boxing/unboxing. This makes our generic stack superior to a nongeneric stack that uses object in place of T (see The object Type for an example).

See All Chapters
Medium 9781449394011

Boolean Type and Operators

Joseph Albahari O'Reilly Media ePub

C#s bool type (aliasing the System.Boolean type) is a logical value that can be assigned the literal true or false.

Although a Boolean value requires only one bit of storage, the runtime will use one byte of memory, since this is the minimum chunk that the runtime and processor can efficiently work with. To avoid space-inefficiency in the case of arrays, the Framework provides a BitArray class in the System.Collections namespace, designed to use just one bit per Boolean value.

== and != test for equality and inequality of any type, and always return a bool value. Value types typically have a very simple notion of equality:

For reference types, equality, by default, is based on reference, as opposed to the actual value of the underlying object. Therefore, two instances of an object with identical data are not considered equal unless the == operator for that type is specially overloaded to that effect (see the section The object Type and the section Operator Overloading).

See All Chapters
Medium 9781449320171

Generics

Joseph Albahari O'Reilly Media ePub

C# has two separate mechanisms for writing code that is reusable across different types: inheritance and generics. Whereas inheritance expresses reusability with a base type, generics express reusability with a template that contains placeholder types. Generics, when compared to inheritance, can increase type safety and reduce casting and boxing.

A generic type declares type parametersplaceholder types to be filled in by the consumer of the generic type, which supplies the type arguments. Here is a generic type, Stack<T>, designed to stack instances of type T. Stack<T> declares a single type parameter T:

We can use Stack<T> as follows:

Notice that no downcasts are required in the last two lines, avoiding the possibility of a runtime error and eliminating the overhead of boxing/unboxing. This makes our generic stack superior to a nongeneric stack that uses object in place of T (see The object Type for an example).

See All Chapters
Medium 9780596519247

Building Query Expressions

Joseph Albahari O'Reilly Media ePub

So far, when weve needed to dynamically compose queries, weve done so by conditionally chaining query operators. Although this is adequate in many scenarios, sometimes you need to work at a more granular level and dynamically compose the lambda expressions that feed the operators.

In this section, well assume the following Product class:

Recall that:

Local queries, which use Enumerable operators, take delegates.

Interpreted queries, which use Queryable operators, take expression trees.

We can see this by comparing the signature of the Where operator in Enumerable and Queryable:

When embedded within a query, a lambda expression looks identical whether it binds to Enumerable s operators or Queryable s operators:

When you assign a lambda expression to an intermediate variable, however, you must be explicit about whether to resolve to a delegate (i.e., Func<>) or an expression tree (i.e., Expression<Func<>>).

You can convert an expression tree to a delegate by calling Compile. This is of particular value when writing methods that return reusable expressions. To illustrate, well add a static method to the Product class that returns a predicate evaluating to true if a product is not discontinued, and has sold in the past 30 days:

See All Chapters
Medium 9780596519223

Enumeration and Iterators

Joseph Albahari O'Reilly Media ePub

An enumerator is a read-only, forward-only cursor over a sequence of values. An enumerator is an object that either:

Implements IEnumerator or IEnumerator<T>

Has a method named MoveNext for iterating the sequence, and a property called Current for getting the current element in the sequence

The foreach statement iterates over an enumerable object. An enumerable object is the logical representation of a sequence, and is not itself a cursor, but an object that produces cursors over itself. An enumerable object either:

Implements IEnumerable or IEnumerable<T>

Has a method named GetEnumerator that returns an enumerator

IEnumerator and IEnumerable are defined in System. Collections. IEnumerator<T> and IEnumerable<T> are defined in System.Collections.Generic.

The enumeration pattern is as follows:

Here is the high-level way of iterating through the characters in the word "beer" using a foreach statement:

See All Chapters

See All Slices