Concepts

A generic definition (IGenericDefinition) is a type or method that has generic parameters.

A specialization of a generic definition constructed by binding concrete arguments to formal generic parameters is called a generic instance (IGenericInstance).

Note that we have used the terms generic parameter (GenericParameterDeclaration) for formal parameters of generic definitions and generic argument, for generic instances, to mean the concrete types bound on formal parameters of generic instances.

Generic definitions and instances have no other common semantics than owning generic parameters and arguments, respectively.

The set of generic arguments bound to generic parameters in a given context is called the generic map (GenericMap) and each MSIL construction (instruction or metadata element) is said to have a generic context, i.e. a mapping of formal generic arguments to concrete generic parameters.

Generic parameters (or more precisely the generic argument to which they are bound at runtime) can be referred to in type signatures. This reference is implemented by the class. Semantics that are common to generic parameters and references to generic parameters are represented by the IGenericDefinition interface.

Example

Take the following C# example:

void SetValue<T>( T value )
{
this.value = value;
}

void Main()
{
SetValue<string>("Hello, world.");
}

The method SetValue<T>(T) is a generic definition, but SetMethod<string>(string) is a generic instance. The first occurrence of T (in "<T>") is a generic parameter, the second one (in "(T value)"), is a reference to the generic parameter. The type string is the generic argument bound to the generic parameter T.

Differences between PostSharp and System.Reflection

System.Reflection always resolves completely generic parameters when you reflect a generic method instance to its MethodBase or a generic type instance to its Type.

For instance, if you reflect the SetValue<string> generic method instance, you will find that the type of the first parameter is string. But this is a simplification and does not correspond to CIL specifications! If you reflect the same generic method instance using PostSharp, you will find that the type of the first parameter is !!0, where !!0 is a reference to the first method generic argument.

Generic Parameters

Generic parameters are belong to a generic method (MethodDefDeclaration) or a generic type (TypeDefDeclaration) and are represented by the GenericParameterDeclaration class. Generic parameters have a name, some attributes and optionally a set of constraints.

A constraint of a generic parameter is a class or an interface that the generic argument bound to this generic parameter is required to inherit or implement.

References to generic parameters are represented as instances of the GenericParameterTypeSignature class.

Semantics that are common to both generic parameters and references to generic parameters are specified in the IGenericParameter interface:

More about Generic Context

The generic context of a generic declaration is a mapping between generic parameters and their associated content.

Now consider the following, more difficult construct:

class A
{
void Method<T1,T2>(T1 a, T2 b);
}

class B<T3>
{
void Method<T4>(T3 a, T4 b)
{ A.Method<T3,T4>(a, b); } }

class C {
void Method()
{
B<int>.Method<string>("Hello, world.");
}
}

We have the following contexts:

Construct

Generic context

A

Empty

A.Method

!!0 → T1, !!1 → T2

B

!0 → T3

B.Method

!0 → T3, !!0 → T4

A.Method<T3,T4>

!!0 → !0, !!1 → !!0

B<int>.Method<string>;

!0 → int !!0 → string