I want to answer a bit deeply.
First of all, let's ask that question.
How CLR treats with generic method?
When a method that uses generic type parameters is JIT-compiled, the CLR takes the method’s IL, substitutes the specifed type arguments, and then creates native code that is specifc to that method operating on the specifed data types. It is called Code Explosion.
In which way does CLR generate that native code? Is there any rules?
CLR keeps generating native code for every method/type combination. If any type argument is a value type, the CLR must produce native code specifically for that value type. The reason is because value types can vary in size.
But, in case of reference types, CLR has some optimization. The CLR considers all reference type arguments to be identical. and so again, the code can be shared. For example, the code compiled by the CLR for List<String>
’s methods can be used for List<Stream>
’s methods, because String
and Stream
are both reference types. In fact, for any reference type, the same code will be used. The CLR can perform this optimization because all reference type arguments or variables are really just pointers.
The source of that explanation is Jeffrey Ritcher's book. (CLR via C#)
And now we come down to your question:
I can't understand how the C# compiler knows what type it deals with?
As you already aware that CLR uses pointers for reference type generic arguments. Of course, that pointers points to some object on heap. And every object on the heap requires some additional members. And one of them is called type object pointer. And that pointer points to the corresponding Type
object which is stored on the heap. And, CLR uses that info to get the type of the object.