While it's true that not all value types
have to be stored on the stack, it is true that a string has to be stored on the heap (this is often given as the reason - string can be huge so they couldn't be stored on the stack).
In theory, a string could well have been a value type, but the value would simply have been the reference to the string. When .NET was first developed, structs were seriously inefficient and the language designers decided to follow the Java convention whereby a string was not a native type, but rather a reference type.
One other point to consider - if a string were a value type then converting it to an object would require a very inefficient boxing operation. Have a look at
this[
^] article to understand why this would be bad.