Compartir a través de


Método System.String.Intern

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

Common Language Runtime conserva el almacenamiento de cadenas manteniendo una tabla, denominada grupo de internados, que contiene una sola referencia a cada cadena literal única declarada o creada mediante programación en el programa. Por lo tanto, una instancia de una cadena literal con un valor determinado solo 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 del grupo de internados y la asigna a cada variable.

El método Intern usa el grupo de internes para buscar una cadena igual al valor de su parámetro, str. Si existe dicha cadena, se devuelve su referencia en el grupo de internados. Si la cadena no existe, se agrega una referencia al grupo de internamiento str y luego se devuelve esa referencia. (Por el contrario, el método IsInterned(String) devuelve una referencia nula si la cadena solicitada no existe en el grupo de internamiento).

En el ejemplo siguiente, la cadena s1, que tiene un valor de "MyTest", ya está internada porque es un literal del programa. La System.Text.StringBuilder clase genera un nuevo objeto de cadena que tiene el mismo valor s1que . Una referencia a esa cadena se asigna a s2. El Intern método busca una cadena que tenga el mismo valor que s2. Dado que existe una cadena de este tipo, el método devuelve la misma referencia que se asigna a s1. A continuación, esa referencia se asigna a s3. Referencias s1 y s2 se comparan de forma desigual porque hacen referencia a objetos diferentes; referencias s1 y s3 se comparan igual porque hacen referencia a la misma cadena.

string s1 = "MyTest"; 
string s2 = new StringBuilder().Append("My").Append("Test").ToString(); 
string s3 = String.Intern(s2); 
Console.WriteLine((Object)s2==(Object)s1); // Different references.
Console.WriteLine((Object)s3==(Object)s1); // The same reference.
let s1 = "MyTest"
let s2 = StringBuilder().Append("My").Append("Test").ToString()
let s3 = String.Intern s2
printfn $"{s2 :> obj = s1 :> obj}" // Different references.
printfn $"{s3 :> obj = s1 :> obj}" // The same reference.
Dim s1 As String = "MyTest" 
Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString() 
Dim s3 As String = String.Intern(s2) 
Console.WriteLine(CObj(s2) Is CObj(s1))      ' Different references.
Console.WriteLine(CObj(s3) Is CObj(s1))      ' The same reference.

Consideraciones sobre el rendimiento

Si intenta reducir la cantidad total de memoria que asigna la aplicación, tenga en cuenta que la internación de una cadena tiene dos efectos secundarios no deseados. En primer lugar, es poco probable que la memoria asignada para los objetos internados String sea liberada hasta que se termine el Common Language Runtime (CLR). El motivo es que la referencia de CLR al objeto interno String puede persistir después de que la aplicación, o incluso el dominio de la aplicación, finalice. En segundo lugar, para internar una cadena, primero debe crear la cadena. La memoria usada por el objeto String todavía debe asignarse, aunque la memoria finalmente será recogida por el recolector de basura.

El miembro de enumeración CompilationRelaxations.NoStringInterning marca un ensamblado como que no requiere la intercalación de literales de cadena. Puede aplicar NoStringInterning a un ensamblado mediante el CompilationRelaxationsAttribute atributo . Además, cuando se usa Ngen.exe (Generador de imágenes nativas) para compilar un ensamblado con antelación del tiempo de ejecución, las cadenas no se intercalan entre módulos.