First, to correct a fallacy in the question, int
and System.Int32
are synonymous. MyGenericType<int>
and MyGenericType<Int32>
are exactly the same type.
Secondly, to address the question (and slightly expand on Mehrdad's answer): consider what the CLR needs to know about a type. It includes:
- The size of a value of that type (i.e. if you have a variable of some type, how much space will that memory need?)
- How to treat the value in terms of garbage collection: is it a reference to an object, or a value which may in turn contain other references?
For all reference types, the answers to these questions are the same. The size is just the size of a pointer, and the value is always just a reference (so if the variable is considered a root, the GC needs to recursively descend into it).
For value types, the answers can vary significantly. For instance, consider:
struct First
{
int x;
object y;
}
struct Second
{
object a;
int b;
}
When the GC looks at some memory, it needs to know the difference between First
and Second
so it can recurse into y
and a
but not x
and b
. I believe this information is generated by the JIT. Now consider the information for List<First>
and List<Second>
- it differs, so the JIT needs to treat the two differently.
Apologies if this isn't as clear as it might be - this is somewhat deep stuff, and I'm not as hot on CLR details as I might be.