Search code examples
c#genericsclrcil

How can c# share the generic implementations of reference types when 'typeof' and 'is' are used?


As far as I understand, at runtime the CLR implementation creates different machine code (or whatever runtime representation) for the same generic Type with different parameterized valuetypes, but shares the machine code for reference types. This makes sense since reference types are going to take up the same size (the size of a reference).

What I don't understand is how this can work with code that explicitly uses code which depends on the type of T directly through something like typeof(T) or is T. For example, in the class:

class TestClass<T> 
{
    public static bool TestAType(Object pObj) { return pObj is T; }
}

I don't see how the same implementation for T = List and T = String can allow TestClass<String>.TestAType("hello") to be true and TestClass<List<int>>.TestAType("hello") to be false.

I'm making the assumption here that the machine code is the same for the compiled generic types, which could of course be false.


Solution

  • The native code generated for each generic instantiation using reference types is indeed the same (having System.__Canon as the parameter internally) but that doesn't mean the code should have no access to the original type arguments. The native code can access the metadata via helper functions and retrieve the types.

    It would be useful to examine actual native code generated by such a method, but from browsing the SSCLI, it looks like this function does the job, according to its description:

    // Given information about how to do a runtime lookup, generate the tree
    // for the runtime lookup.
    //
    // Run-time lookup is required if the enclosing method is shared between instantiations
    // and the token refers to formal type parameters whose instantiation is not known
    // at compile-time.