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);




    Type type2 = typeof(G<int>).GetNestedType("NestedC");





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

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?





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

  {  ...