System.String.Intern 方法

本文提供此 API 參考文件的補充備註。

Common Language Runtime 藉由維護稱為「實習生集區」的數據表來節省字串儲存空間,該數據表包含以程序設計方式宣告或建立的每個唯一常值字元串的單一參考。 因此,具有特定值的常值字串實例只存在於系統中一次。

例如,如果您將相同的常值字串指派給數個變數,運行時間會從實習生集區擷取對常值字串的相同參考,並將它指派給每個變數。

方法 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指派給 。 然後,和 str2 中包含的str1參考會比較是否相等。 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

效能考量

如果您嘗試減少應用程式配置的記憶體總量,請記住,插入字串有兩個不必要的副作用。 首先,在 Common Language Runtime (CLR) 終止之前,配置給實習生 String 對象的記憶體不太可能釋放。 原因是 CLR 對實習生 String 對象的參考可以在您的應用程式甚至應用程式域終止之後保存。 其次,若要實習生字串,您必須先建立字串。 物件所使用的 String 記憶體仍必須配置,即使記憶體最終會被垃圾收集也一樣。

列舉成員會將 CompilationRelaxations.NoStringInterning 元件標示為不需要字串常值插入。 您可以使用 屬性套用NoStringInterningCompilationRelaxationsAttribute至元件。 此外,當您使用 Ngen.exe (Native Image Generator) 在運行時間之前編譯元件時,不會跨模組內實習生字串。