String.Intern(String) Метод

Определение

Извлекает ссылку системы на указанный Stringобъект.

public:
 static System::String ^ Intern(System::String ^ str);
public static string Intern(string str);
static member Intern : string -> string
Public Shared Function Intern (str As String) As String

Параметры

str
String

Строка для поиска в интерновом пуле.

Возвращаемое значение

Ссылка системы strна , если она интернирована; в противном случае новая ссылка на строку со значением str.

Исключения

str равно null.

Примеры

В следующем примере создаются две строки с равными значениями и демонстрируется, что их взаимодействие дает одну и ту же ссылку.

// Sample for String.Intern(String)
using System;
using System.Text;

class Sample
{
    public static void Main()
    {
        string s1 = new StringBuilder().Append("My").Append("Test").ToString();
        string s2 = new StringBuilder().Append("My").Append("Test").ToString();
        Console.WriteLine($"s1 == {s1}");
        Console.WriteLine($"s2 == {s2}");
        Console.WriteLine($"Are s1 and s2 equal in value? {s1 == s2}");
        Console.WriteLine($"Are s1 and s2 the same reference? {Object.ReferenceEquals(s1, s2)}");

        string i1 = String.Intern(s1);
        string i2 = String.Intern(s2);
        Console.WriteLine($"After interning:");
        Console.WriteLine($"  Are i1 and i2 equal in value? {i1 == i2}");
        Console.WriteLine($"  Are i1 and i2 the same reference? {Object.ReferenceEquals(i1, i2)}");
    }
}
/*
This example produces the following results:
s1 == MyTest
s2 == MyTest
Are s1 and s2 equal in value? True
Are s1 and s2 the same reference? False
After interning:
  Are i1 and i2 equal in value? True
  Are i1 and i2 the same reference? True
*/
// Sample for String.Intern(String)
open System
open System.Text

let s1 = StringBuilder().Append("My").Append("Test").ToString()
let s2 = StringBuilder().Append("My").Append("Test").ToString()
printfn $"s1 = {s1}"
printfn $"s2 = {s2}"
printfn $"Are s1 and s2 equal in value? {s1 = s2}"
printfn $"Are s1 and s2 the same reference? {Object.ReferenceEquals(s1, s2)}"

let i1 = String.Intern s1
let i2 = String.Intern s2
printfn "After interning:"
printfn $"  Are i1 and i2 equal in value? {i1 = i2}"
printfn $"  Are i1 and i2 the same reference? {Object.ReferenceEquals(i1, i2)}"
(*
This example produces the following results:
s1 = MyTest
s2 = MyTest
Are s1 and s2 equal in value? True
Are s1 and s2 the same reference? False
After interning:
  Are i1 and i2 equal in value? True
  Are i1 and i2 the same reference? True
*)
Imports System.Text

Class Sample

    Public Shared Sub Run()
        Dim s1 As String = New StringBuilder().Append("My").Append("Test").ToString()
        Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString()
        Console.WriteLine($"s1 = {s1}")
        Console.WriteLine($"s2 = {s2}")
        Console.WriteLine($"Are s1 and s2 equal in value? {s1 = s2}")
        Console.WriteLine($"Are s1 and s2 the same reference? {s1 Is s2}")

        Dim i1 As String = String.Intern(s1)
        Dim i2 As String = String.Intern(s2)
        Console.WriteLine("After interning:")
        Console.WriteLine($"  Are i1 and i2 equal in value? {i1 = i2}")
        Console.WriteLine($"  Are i1 and i2 the same reference? {i1 Is i2}")
    End Sub
End Class
'
's1 = MyTest
's2 = MyTest
'Are s1 and s2 equal in value? True
'Are s1 and s2 the same reference? False
'After interning:
'  Are i1 and i2 equal in value? True
'  Are i1 and i2 the same reference? True
'

Комментарии

! [ПРИМЕЧАНИЕ] > Хотя String.Intern гарантирует, что две строки с равными значениями возвращают одну и ту же интернированную ссылку, она не гарантирует, что возвращенная ссылка совпадает с строковым литералом.

        The common language runtime maintains a table, called the *intern pool*, that holds a single reference for each unique string value. The <xref:System.String.Intern*> method uses the intern pool to search for a string equal to the value of `str`. If no such string exists, a reference to `str` is added to the pool, and that reference is returned. (In contrast, the <xref:System.String.IsInterned(System.String)> method returns a null reference if the requested string doesn't exist in the intern pool.)

Интерн-пул можно использовать средой выполнения для экономии строкового хранилища. Однако автоматическое интернирование строковых литералов не гарантируется — в зависимости от того, как была скомпилирована и выполнена сборка, некоторые литералы могут не добавляться в пул.

В следующем примере строка s1 имеет значение MyTest. Класс System.Text.StringBuilder создает новый строковый объект, имеющий то же значение, что s1и . Ссылка на эту строку присваивается s2. Метод Intern ищет строку, которая имеет то же значение, что s2. Если s1 уже была интернирована (например, потому что для сборки требуется интернирование строкового литерала), метод возвращает ту же ссылку, что и s1, затем присваивается s3, и s1, s3 сравниваются как равные. В противном случае создается новая интернированная запись для s2 и назначается s3, а s1 и s3 сравниваются как неравные. В любом случае, s1 и s2 считаются неравными, потому что они ссылаются на разные объекты.

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.

Вопросы производительности

Если вы пытаетесь уменьшить общий объем памяти, который выделяет ваше приложение, запомните, что при интернировании строки возникают два нежелательных побочных эффекта. Во-первых, память, выделенная для интернированных String объектов, скорее всего, не будет освобождена до тех пор, пока общеязыковая среда выполнения (CLR) не завершит работу. Причина заключается в том, что ссылка среды CLR на интернированный String объект может сохраняться после завершения приложения или даже домена приложения. Во-вторых, чтобы интернировать строку, необходимо сначала создать ее. Память, используемая объектом String, по-прежнему должна быть выделена, даже если она в конечном итоге будет передана на сборку мусора.

Член CompilationRelaxations.NoStringInterning перечисления указывает, что сборка не требует интернирования строковых литералов. По умолчанию компилятор C# выдает CompilationRelaxationsAttributeNoStringInterning флаг для каждой сборки для повышения производительности, что означает, что строковые литералы не гарантированно добавляются в интернированный пул. Вы можете настроить NoStringInterning в сборке с помощью атрибута CompilationRelaxationsAttribute.

При публикации приложения с использованием нативного AOT отключение NoStringInterning не поддерживается. При использовании нативного AOT строковые литералы не гарантированно добавляются в интернальный пул строк, поэтому Intern может не найти совпадение для строки, которая является литералом в исходном коде.

Применяется к

См. также раздел