Chapter 1: Generics 101

Parametric Polymorphism
The term is often used to describe the flavor of polymorphism that can be achieved with generic types. Well, instead of achieving polymorphism through inheritance, generics allow you to achieve the functional equivalent by allowing you to parameterize your types. Where regular polymorphism might use a virtual method table to override the methods of a parent object, parametric polymorphism achieves a similar result by allowing a single class to dynamically substitute the types referenced in its internal implementation. This ability to alter a class’s behavior via a type parameter is seen simply as an alternative form of polymorphism, thus the name parametric polymorphism.

Type Parameters
A type parameter refers to the parameter that is used in the definition of your generic type. Each generic type can accept one or more type parameters, and this list of parameters will define the signature of your type. The names used for these parameters are then referenced throughout the implementation of your new type.

Although type parameters can be applied to classes, structs, and interfaces, they cannot be directly applied to indexers, properties, or events. Indexers, properties, and events can all reference type parameters in their signatures; they simply can’t explicitly accept their own type arguments. Instead, those types must be defined as part of the surrounding class.

Open Types
Instead of referring to Stack<T> as a class, generics consider it an “open type.” My assumption here is that the term “open” is meant to convey the idea that the type is not fully defined and is “open” to taking on multiple concrete representations.

Constructed Types
A constructed type, on the other hand, represents a concrete instance of one of your open types e.g. Stack<string> myString

Type Arguments
Whenever you instantiate a constructed type, you must provide specific types for each of the type parameters required by the given open type you are constructing. So, when you declared the constructed type Stack<string> in the preceding section, the string type passed in would be considered a type argument.

Open and Closed Constructed Types
Consider the following code snippet:

public class MyType<T> {
    private constructedType1<Integer> member1;
    private constructedType2<T> member2;

}

This example creates an open type MyType, which has two data members that are constructed types. The first data member, constructedType1, is considered a closed constructed type because its type argument is fixed or “closed” to further definition. Its type argument will always be an Integer. The other data member, constructedType2, throws in a new twist. Instead of passing a concrete type as its type argument, it passes a type argument of T, which is the type parameter defined for the generic type. Despite this variation, the type is still considered a constructed type. However, because its parameter is still open to run-time definition, it is referred to as an open constructed type.

Generic Methods
The following is a very simple example of a generic method:

public T CalculateValue<T>(T myParam1, int myParam2) {
    T var1;
     …
}

Like open types, generic methods also accept a type parameter. And, like open types, generic methods can reference this parameter as part of their signature or implementation. In fact, this example loads up the references to the type parameter to illustrate this point. The return type, one of its parameters, and a local variable all reference the type parameter T.

Type Instantiation
The first time the Just-In-Time (JIT) compiler comes across a constructed type in your code, it must transform that type into the appropriate IL representation. During this process, it will examine each of the incoming type arguments and substitute each of the open type’s parameters with the data types of these arguments. The result will be the accurate run-time representation of your constructed type. This transformation process is considered “type instantiation” because it yields an actual instance of the constructed type.

Arity
Arity simply refers to the number of type parameters that are used by a generic type. So, if your type has three type parameters, it is said to have an arity of 3. And, just to be complete, a type that has no type parameters has an arity of zero.

Generic Types
Generic types is probably the most heavily used term referenced throughout this book. It is the all encompassing term that is intended to describe any class, struct, event, or delegate that accepts one or more type parameters. This term is not really part of any formally accepted generics terminology and is somewhat synonymous with the idea of an open type.

Notes:
1. Any generic class must accept at least one generic parameter <T>.
2. In the code inside the generic class, that class will always be referred as ClassName<T> and its array as ClassName<T>[] (because precisely, the class name itself is ClassName<T>).

Leave a comment