La distinción entre los tipos de referencia y los tipos de valor son básicamente una compensación de rendimiento en el diseño del lenguaje. Los tipos de referencia tienen algunos gastos generales en la construcción y la destrucción y la recolección de basura, ya que se crean en el montón. Por otro lado, los tipos de valor tienen una sobrecarga en las llamadas a métodos (si el tamaño de los datos es mayor que un puntero), porque todo el objeto se copia en lugar de solo un puntero. Debido a que las cadenas pueden ser (y típicamente son) mucho más grandes que el tamaño de un puntero, están diseñadas como tipos de referencia. Además, como señaló Servy, el tamaño de un tipo de valor debe conocerse en el momento de la compilación, que no siempre es el caso de las cadenas.
La cuestión de la mutabilidad es un tema aparte. Tanto los tipos de referencia como los tipos de valor pueden ser mutables o inmutables. Sin embargo, los tipos de valor suelen ser inmutables, ya que la semántica para los tipos de valor mutable puede ser confusa.
Los tipos de referencia son generalmente mutables, pero pueden diseñarse como inmutables si tiene sentido. Las cadenas se definen como inmutables porque hacen posibles ciertas optimizaciones. Por ejemplo, si el mismo literal de cadena aparece varias veces en el mismo programa (que es bastante común), el compilador puede reutilizar el mismo objeto.
Entonces, ¿por qué se sobrecarga "==" para comparar cadenas de texto? Porque es la semántica más útil. Si dos cadenas son iguales por texto, pueden o no ser la misma referencia de objeto debido a las optimizaciones. Por lo tanto, comparar referencias es bastante inútil, mientras que comparar texto es casi siempre lo que desea.
Hablando de manera más general, Strings tiene lo que se denomina semántica de valor . Este es un concepto más general que los tipos de valor, que es un detalle de implementación específico de C #. Los tipos de valor tienen semántica de valor, pero los tipos de referencia también pueden tener semántica de valor. Cuando un tipo tiene semántica de valor, realmente no se puede saber si la implementación subyacente es un tipo de referencia o un tipo de valor, por lo que puede considerar que es un detalle de implementación.
is
lado las pruebas), la respuesta es probablemente "por razones históricas". El rendimiento de la copia no puede ser la razón, ya que no es necesario copiar físicamente objetos inmutables. Ahora es imposible cambiar sin romper el código que realmente usais
cheques (o restricciones similares).