2

In the Generics in the Run Time (C# Programming Guide) it's said that it does and it surprised me. I always thought that under the hood it would create a separate specialized type for every different type parameter no matter whether it is a value or reference type. Maybe because (if my memory serves me right) that's how it was in C++ when I used it.

Anyway, I can't understand how the C# compiler knows what type it deals with if it treats all the reference types just as pointers inside one specialized generic class. For example, when List<T> returns an item it should know which type it returns hence there should be a specialized method/class for it. How does it really work? Does it create a single specialized type only for the system generic collections or for any generic class including custom ones?

Serg
  • 6,742
  • 4
  • 36
  • 54
  • You can have a look at this thread [Where are generic methods stored](https://stackoverflow.com/questions/41461595/where-are-generic-methods-stored) Value types has the different size, so there is s separate constructed generic class for every value type. And only one generic class for reference types, because the same size – Pavel Anikhouski Jan 05 '20 at 13:47
  • Thanks! If I understand it right, for each reference type a specialized type is still generated (since it's available via reflection), but internally there is only one specialized type which treats any reference as a pointer. And all these tricks happen at runtime (not while compiling). – Serg Jan 05 '20 at 14:01
  • Yes, in C# generics are evaluated at runtime, not at compile time – Pavel Anikhouski Jan 05 '20 at 14:03
  • 1
    The literal answer to your question (found also in the marked duplicates) is that **no, the compiler does not create just one type to handle all the different reference types used as the type parameter for the generic type.** Each usage of the generic type with a different type parameter generates a different new reified type for that parameter. However, it _is_ true that for reference types, the _native_ code that ultimately implements that type is shared among all the type parameters. Type safety is ensured at compile type, the `T` values are all references, and so the code can be shared. – Peter Duniho Jan 05 '20 at 14:23

1 Answers1

2

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.

Farhad Jabiyev
  • 26,014
  • 8
  • 72
  • 98