Compartilhar via


Método System.String.Intern

Observação

Este artigo fornece comentários complementares à documentação de referência para esta API.

O Common Language Runtime mantém uma tabela, chamada intern pool, que contém uma única referência para cada valor de cadeia de caracteres exclusivo. O Intern método usa o pool de estagiários para pesquisar uma cadeia de caracteres igual ao valor de str. Se essa cadeia de caracteres não existir, uma referência a str será adicionada ao pool, e essa referência será retornada. (Por outro lado, o IsInterned(String) método retornará uma referência nula se a cadeia de caracteres solicitada não existir no pool de estagiários.)

O pool de estagiários pode ser usado pelo runtime para conservar o armazenamento de cadeias de caracteres. No entanto, a inserção automática de literais de strings não é garantida—dependendo de como o assembly foi compilado e executado, alguns literais podem não ser adicionados ao pool.

No exemplo a seguir, a cadeia de caracteres s1 tem um valor de "MyTest". 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 pesquisa uma cadeia de caracteres que tem o mesmo valor que s2. Se s1 já estiver internado (por exemplo, porque a montagem requer a internação literal de cadeias de caracteres), o método retornará a mesma referência s1 que, em seguida, é atribuída a s3, e s1 e s3 se comparam como iguais. Caso contrário, uma nova entrada internada s2 será criada e atribuída a s3, e s1 e s3 serão comparados como desiguais. Em ambos os casos, s1 e s2 se comparam de forma desigual porque se referem a objetos diferentes.

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.

Considerações sobre desempenho

Se você estiver tentando reduzir a quantidade total de memória alocada pelo aplicativo, tenha em mente que a internação de uma cadeia de caracteres terá 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) seja encerrado. O motivo é que a referência do CLR ao objeto interno String pode persistir após o término do aplicativo ou até mesmo do domínio do aplicativo. Em segundo lugar, para internar uma cadeia de caracteres, primeiro você deve criá-la. A memória usada pelo objeto String ainda deve ser alocada, mesmo que a memória eventualmente seja coletada pelo coletor de lixo.

O membro de enumeração CompilationRelaxations.NoStringInterning marca um assembly como não exigindo internação literal de cadeia de caracteres. Por padrão, o compilador C# emite um CompilationRelaxationsAttribute com o NoStringInterning sinalizador em cada assembly para melhor desempenho, o que significa que literais de cadeia de caracteres não têm garantia de serem adicionados ao pool de estagiários. Você pode personalizar NoStringInterning em um assembly usando o atributo CompilationRelaxationsAttribute.

Quando você publica um aplicativo usando a AOT nativa, não há suporte para desativar NoStringInterning . Com a AOT nativa, não há garantia de que literais de cadeia de caracteres sejam adicionados ao pool de estagiários, portanto Intern , talvez não encontre uma correspondência para uma cadeia de caracteres que parece ser um literal no código-fonte.