System.String.Intern 方法

本文提供了此 API 参考文档的补充说明。

公共语言运行时通过维护名为实习生池的表来节省字符串存储,该表包含对程序中声明或以编程方式声明或创建的每个唯一文本字符串的单个引用。 因此,具有特定值的文字字符串的实例仅在系统中存在一次。

例如,如果将相同的文本字符串分配给多个变量,运行时将从实习生池中检索对文本字符串的相同引用,并将其分配给每个变量。

该方法 Intern 使用实习生池搜索等于值的 str字符串。 如果存在此类字符串,则会在实习生池中返回其引用。 如果该字符串不存在,则会向实习生池添加对 str 的引用,然后返回该引用。

在下面的示例中,字符串 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.

将此方法与 IsInterned 方法进行比较。

在以下示例中,该变量str1被赋给引用String.Empty,并且变量str2在将值String.Empty转换为StringBuilder字符串的对象后,通过调用Intern该方法返回的引用String.Empty。 然后,将包含str1str2的引用与相等进行比较。 str1str2 相等。

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

性能注意事项

如果尝试减少应用程序分配的内存总量,请记住,在字符串间执行操作会产生两个不需要的副作用。 首先,在公共语言运行时 (CLR) 终止之前,为实习生 String 对象分配的内存不太可能释放。 原因是 CLR 对实习生 String 对象的引用可以在应用程序甚至应用程序域终止后保留。 其次,若要实习生字符串,必须先创建字符串。 仍必须分配对象使用的 String 内存,即使内存最终会被垃圾回收。

CompilationRelaxations.NoStringInterning枚举成员将程序集标记为不需要字符串文本插入。 可以使用特性CompilationRelaxationsAttribute应用于NoStringInterning程序集。 此外,使用 Ngen.exe(本机映像生成器) 在运行时之前编译程序集时,不会跨模块对字符串进行实习生处理。