2010-02-09 15 views
16

una)Dado que las cadenas son inmutables, ¿las variables con valores de cadena idénticos apuntan al mismo objeto de cadena?

 string s = "value"; 
     string s1 = "value"; 

Do s s1 y variables de referencia apuntan a un mismo objeto string (Asumo esto debido al hecho de que las cadenas son inmutables)?

b) Me doy cuenta de que los operadores de igualdad (==,> etc) se han redefinido para comparar los valores de los objetos de cadena, pero es lo mismo cuando se comparan dos cadenas utilizando métodos estáticos Object.Equals() y Object.ReferenceEquals ()?

Gracias

+2

No soy un experto pero eche un vistazo a este enlace sobre la internación de cadenas. http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool – ChaosPandion

+10

Vea también mi artículo sobre esto para algunos comentarios adicionales: http://blogs.msdn.com/ericlippert/archive/2009/09/ 28/string-interning-and-string-empty.aspx –

+0

@Eric - Gran lectura, gracias por publicar el enlace. – ChaosPandion

Respuesta

21

No, no todas las cadenas con el mismo valor son la misma referencia de objeto.

Las cadenas generadas por el compilador se internarán y serán la misma referencia. Las cadenas generadas en tiempo de ejecución no se internan por defecto y serán referencias diferentes.

var s1 = "abc"; 
var s2 = "abc"; 
var s3 = String.Join("", new[] {"a", "b", "c"}); 
var s4 = string.Intern(s3); 
Console.WriteLine(ReferenceEquals(s1, s2)); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s3)); // Returns False 
Console.WriteLine(s1 == s3); // Returns True 
Console.WriteLine(ReferenceEquals(s1, s4)); // Returns True 

Nota por encima de la línea donde se puede forzar una cadena a ser internados utilizando String.Intern(string) que a su vez permite el uso de igualdad de objetos en lugar de igualdad de cadenas de algunos cheques, lo cual es mucho más rápido. Un ejemplo en el que esto se usa con mucha frecuencia es dentro del código de serializador XML generado junto con la tabla de nombres.

+1

+1 para aclarar que las cadenas creadas en tiempo de ejecución tienen que ser internadas manualmente. – ChaosPandion

+0

Puede valer la pena agregar var s4 = string.Intern (s3); Console.WriteLine (ReferenceEquals (s1, s4)); // Devuelve True – Dolphin

+0

@Dolphin, buen punto, actualicé la respuesta. –

3

Sí, estos se apuntan a la misma cadena, porque son ambos definidos como literales de cadena. Si crea una cadena programáticamente, tendrá que internar manualmente la cadena.

Esto se debe a que .NET framework interna los literales de cadena en su programa en el grupo interno. Puede usar String.Intern para recuperar esta referencia o para internar manualmente su propia cadena generada en el tiempo de ejecución.

Para más detalles, referirse a la docs for Intern:

consecuencia, una instancia de una cadena literal con un valor particular sólo existe una vez en el sistema.

Por ejemplo, si asigna la misma cadena literal a varias variables, el tiempo de ejecución recupera la misma referencia a la cadena literal de la piscina interno y lo asigna a cada variable

+2

Sin embargo, esto es por implementación, no especificación. –

+0

Cierto, pero la implementación sí lo hace, actualmente, para valores literales. –

+0

Agregué algunas aclaraciones en mi respuesta. –

2

Con el CLR actual idéntica literal las cadenas apuntan a los mismos objetos reales. El proceso se denomina internamiento y se aplica a todas las cadenas de tiempo de compilación.

Las cadenas creadas en tiempo de ejecución no se internan por defecto, pero se pueden agregar a la colección interna llamando al string.Intern.

Consulte my answer for this question para obtener una explicación detallada de cómo se almacenan las cadenas .NET.

Cuestiones relacionadas