本文提供此 API 參考文件的補充備註。
Common Language Runtime 藉由維護稱為 「內部存放區」的表格來節省字串儲存空間,該表格包含在程式中宣告或建立的每個唯一字面字串的單一參考。 因此,具有特定值的常值字串實例只存在於系統中一次。 例如,如果您將相同的常值字串指派給數個變數,運行時間會從實習生集區擷取對常值字串的相同參考,並將它指派給每個變數。
方法 Intern 會使用實習生集區來搜尋等於其參數值的字串, str。 如果存在這類字串,則會傳回其在實習生集區中的參考。 如果字串不存在,則會將str的參考新增至字串內部池,然後傳回該參考。 (相反地,如果要求字串不存在於實習生集區中, IsInterned(String) 此方法會傳回 Null 參考。
在下列範例中,具有「MyTest」值的字串 s1 已經被實體化,因為它是程式中的文字常數。 類別 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 對象的記憶體在 Common Language Runtime(CLR)終止之前不太可能被釋放。 原因是 CLR 對內部化 String 對象的引用,即使在您的應用程式甚至應用程式域終止之後,也可以持續存在。 其次,若要將字串實化,您必須先建立字串。 物件所使用的 String 記憶體仍必須配置,即使記憶體最終會被垃圾收集也一樣。
列舉成員會將 CompilationRelaxations.NoStringInterning 組件標示為不需要字串常值實例化。 您可以將 NoStringInterning 套用至組件,使用CompilationRelaxationsAttribute屬性。 另外,當你用 Ngen.exe(原生影像產生器) 在執行前編譯組合語言時,字串不會跨模組內嵌。