Nested Types in Generic Classes
In C#, nested types can be defined in generic classes just like they would be in
non-generic classes. For example:
class G<T> {
public class NestedC { }
public enum NestedEnum { A, B }
}
Inside the nested type NestedC, we can still use type parameter T, which was "declared"
with class G<T>. Actually this is a misconception (the C# compiler does some
magic behind the scenes). If we were to use ildasm to view the node of NestedC,
we would find "NestedC" is a generic type with type parameter "T". As far as the
runtime is concerned, this "T" is not the same as the "T" with G<T>; they
just happen to have the same name.
.class private auto ansi beforefieldinit G`1<T>
extends [mscorlib]System.Object
{
.class auto ansi nested public beforefieldinit NestedC<T>
extends [mscorlib]System.Object
{ ...
When we use T inside NestedC, we are in fact referring to NestedC's own T, the type
parameter "T" declared with NestedC<T>. With that in mind, let us think about
what the following code will print:
class Test {
static void Main() {
Type type1 = typeof(G<int>.NestedC);
Console.WriteLine(type1);
Console.WriteLine(type1.IsGenericTypeDefinition);
Type type2 = typeof(G<int>).GetNestedType("NestedC");
Console.WriteLine(type2);
Console.WriteLine(type2.IsGenericTypeDefinition);
}
}
1. typeof(G<int>.NestedC) is translated by C# compiler to
IL_0001: ldtoken class G`1/NestedC<int32>
IL_0006: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype
[mscorlib]System.RuntimeTypeHandle)
The generic argument "int32" is bound to NestedC<>, not G<>;
2. You might already have noticed that although both are generic types, "NestedC"
does not have `(grave accent), but "G`1" does. So typeof(G<int>).GetNestedType("NestedC")
will get back the open generic type "NestedC<>".
Here is the result, is it as you expected?
G`1+NestedC[System.Int32]
False
G`1+NestedC[T]
True
In summary, when written in C#, every type defined under a generic type will be
a generic type (including enum; C# does not allow us to explicitly define a generic
enum). To define a truly non-generic nested type inside a generic type, IL can help:
.class private auto ansi beforefieldinit G`1<T>
extends [mscorlib]System.Object
{
.class auto ansi nested public beforefieldinit NestedNonGenericC
extends [mscorlib]System.Object
{ ...
Comments
- Anonymous
February 17, 2006
Type.FullName
returns null when the type is not generic type definition but contains...