From the MSDN Generics in the Run Time document I note:
When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Specialized generic types are created one time for each unique value type that is used as a parameter.
and
Generics work somewhat differently for reference types. The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with object references substituted for the parameters in the MSIL. Then, every time that a constructed type is instantiated with a reference type as its parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the generic type. This is possible because all references are the same size.
Am I correct to infer from this that, although the string data-type possesses value-type semantics in both C# and the CLR, a generic type instantiated with a string type parameter will use the same specialized generic type as the other reference types, rather than having its own as other value-type would? Has this behaviour, either way, been the same since V2 when generics were introduced?
string
is a reference type in every way. It has "value-type semantics" in the Wikipedia sense, but that doesn't make it a value type in the terminology used in MSDN. In the common CLR and C# terminology which divides all non-pointer types into "reference types" or "value types", a string is definitely a reference type. Note that you can easily build your own reference type with value semantics too - but it will still be a reference type in every way that the specifications care.
See more on this question at Stackoverflow