A String is a reference type even though it has most of the characteristics of a value type such as being immutable and having == overloaded to compare the text rather than
This is a late answer to an old question, but all other answers are missing the point, which is that .NET did not have generics until .NET 2.0 in 2005.
String
is a reference type instead of a value type because it was of crucial importance for Microsoft to ensure that strings could be stored in the most efficient way in non-generic collections, such as System.Collections.ArrayList
.
Storing a value-type in a non-generic collection requires a special conversion to the type object
which is called boxing. When the CLR boxes a value type, it wraps the value inside a System.Object
and stores it on the managed heap.
Reading the value from the collection requires the inverse operation which is called unboxing.
Both boxing and unboxing have non-negligible cost: boxing requires an additional allocation, unboxing requires type checking.
Some answers claim incorrectly that string
could never have been implemented as a value type because its size is variable. Actually it is easy to implement string as a fixed-length data structure using a Small String Optimization strategy: strings would be stored in memory directly as a sequence of Unicode characters except for large strings that would be stored as a pointer to an external buffer. Both representations can be designed to have the same fixed length, i.e. the size of a pointer.
If generics had existed from day one I guess having string as a value type would probably have been a better solution, with simpler semantics, better memory usage and better cache locality. A List
containing only small strings could have been a single contiguous block of memory.