Método System.String.Intern

Este artigo fornece observações complementares à documentação de referência para essa API.

O Common Language Runtime conserva o armazenamento de cadeias de caracteres mantendo uma tabela, chamada pool interno, que contém uma única referência a cada cadeia de caracteres literal exclusiva declarada ou criada programaticamente em seu programa. Consequentemente, uma instância de uma cadeia de caracteres literal com um valor específico só existe uma vez no sistema.

Por exemplo, se você atribuir a mesma cadeia de caracteres literal a várias variáveis, o tempo de execução recuperará a mesma referência à cadeia de caracteres literal do pool interno e a atribuirá a cada variável.

O Intern método usa o pool interno para procurar uma cadeia de caracteres igual ao valor de str. Se essa cadeia de caracteres existir, sua referência no pool interno será retornada. Se a cadeia de caracteres não existir, uma referência a str for adicionada ao pool interno, essa referência será retornada.

No exemplo a seguir, a cadeia de caracteres s1, que tem um valor de "MyTest", já está internada porque é um literal no programa. A System.Text.StringBuilder classe gera um novo objeto de cadeia de caracteres que tem o mesmo valor que s1. Uma referência a essa cadeia de caracteres é atribuída a s2. O Intern método procura uma cadeia de caracteres que tenha o mesmo valor que s2. Como essa cadeia de caracteres existe, o método retorna a mesma referência atribuída a s1. Essa referência é então atribuída a s3. As referências s1 e s2 comparam-se desiguais por se referirem a objetos diferentes; As referências S1 e S3 comparam-se iguais porque se referem à mesma cadeia de caracteres.

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.

Compare esse método com o IsInterned método.

No exemplo a seguir, a variável recebe uma referência a , e a variável str1str2 recebe a referência a String.EmptyString.Empty que é retornada chamando o Intern método depois de converter um StringBuilder objeto cujo valor é String.Empty em uma cadeia de caracteres. Em seguida, as referências contidas e str1str2 são comparadas para a igualdade. str1 e str2 são iguais.

string str1 = String.Empty;
string str2 = String.Empty;

StringBuilder sb = new StringBuilder().Append(String.Empty);
str2 = String.Intern(sb.ToString());

if ((object)str1 == (object)str2)
    Console.WriteLine("The strings are equal.");
else
    Console.WriteLine("The strings are not equal.");
let str1 = String.Empty
let str2 = String.Empty

let sb = StringBuilder().Append String.Empty
let str3 = String.Intern(string sb)

if (str1 :> obj) = (str3 :> obj) then
    printfn "The strings are equal."
else
    printfn "The strings are not equal."
Dim str1 As String = String.Empty
Dim str2 As String = String.Empty

Dim sb As StringBuilder = New StringBuilder().Append(String.Empty)
str2 = String.Intern(sb.ToString())

If CObj(str1) Is CObj(str2) Then
    Console.WriteLine("The strings are equal.")
Else
    Console.WriteLine("The strings are not equal.")
End If

Considerações sobre o desempenho

Se você estiver tentando reduzir a quantidade total de memória que seu aplicativo aloca, tenha em mente que internar uma cadeia de caracteres tem dois efeitos colaterais indesejados. Primeiro, a memória alocada para objetos internos String provavelmente não será liberada até que o CLR (Common Language Runtime) termine. O motivo é que a referência do CLR ao objeto internado String pode persistir depois que seu aplicativo, ou até mesmo seu domínio de aplicativo, termina. Em segundo lugar, para estagiar uma cadeia de caracteres, você deve primeiro criar a cadeia de caracteres. A memória usada pelo String objeto ainda deve ser alocada, mesmo que a memória acabe sendo coletada como lixo.

O CompilationRelaxations.NoStringInterning membro de enumeração marca um assembly como não exigindo estágio literal de cadeia de caracteres. Você pode aplicar NoStringInterning a um assembly usando o CompilationRelaxationsAttribute atributo . Além disso, quando você usa Ngen.exe (Native Image Generator) para compilar um assembly antes do tempo de execução, as cadeias de caracteres não são internadas entre módulos.