Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
Среда CLR экономит хранилище строк, сохраняя таблицу, называемую интернальным пулом, которая содержит одну ссылку на каждую уникальную литеральную строку, объявленную или созданную программным способом в программе. Следовательно, экземпляр литеральной строки с определенным значением существует только один раз в системе. Например, если вы назначаете одну литеральную строку нескольким переменным, среда выполнения извлекает одну и ту же ссылку на литеральную строку из внутреннего пула и назначает ее каждой переменной.
Метод Intern использует интерновый пул для поиска строки, равной значению его параметра str
. Если такая строка существует, возвращается ссылка из интернированного пула строк. Если строка не существует, ссылка str
добавляется в интернирующий пул, и та же самая ссылка возвращается. (В отличие от этого, метод IsInterned(String) возвращает нулевую ссылку, если запрошенная строка не существует в интернированном пуле.)
В следующем примере строка s1
, которая имеет значение MyTest, уже интернирована, так как это литерал в программе. Класс System.Text.StringBuilder создает новый строковый объект, имеющий то же значение, что s1
и . Ссылка на эту строку присваивается s2
. Метод Intern ищет строку, которая имеет то же значение, что s2
. Так как такая строка существует, метод возвращает ту же ссылку, которая присвоена s1
. Затем эта ссылка присваивается s3
. Ссылки s1
и s2
не равны, так как они ссылаются на разные объекты; s1
и s3
равны, так как они ссылаются на одинаковую строку.
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 перечисления указывает, что сборка не требует интернирования строковых литералов. Вы можете применить NoStringInterning к сборке с помощью атрибута CompilationRelaxationsAttribute . Кроме того, при использовании Ngen.exe (генератор собственных образов) для компиляции сборки заранее времени выполнения строки не интернируются между модулями.