string s1 = "original";
string s2 = s1; // 此時 s1、s2 指向同一個堆上物件
s1 = "changed"; // s1 指向新物件,s2 仍指向原物件
Console.WriteLine(s1); // changed
Console.WriteLine(s2); // original ← 未受影響!
明明是參考型別,修改其中一個變數卻不影響另一個,違背直覺。
string 是 不可變 類型:任何「修改」操作 (連接、替換、Substring…) 都會在堆上建立 全新物件,原物件保持不變。= 對參考型別只是複製「參考」;但後續的「修改」實為「重新指派新物件」,故原參考所指物件不變。string a = "abc";
string b = "abc";
Console.WriteLine(object.ReferenceEquals(a, b)); // True!指向同一個物件
CLR 維護一張 內部駐留表 (Intern Pool):
ldstr IL 指令) 自動駐留。string.Intern() 可手動駐留。String.Equals 靜態多載會先比較參考相等,極大提升常見字串比較效能。| 多載 | 行為 | 用途 |
|---|---|---|
Equals(object) | 虛方法,內部呼叫 CompareOrdinal 逐字元比較 | 多型比較 |
Equals(string) | 強型別版本,同樣逐字元比較 | 避免裝箱 |
Equals(string, string) | 靜態方法,先比參考相等,相等即回傳 true,否則逐字元比較 | 高效能比較首選 |
StringBuilder 或 string.Create (高效能場景)。string.Equals(a, b, StringComparison.Ordinal) 或 == (已針對駐留優化)。char[] 或 Span<char>。ReferenceEquals 判斷字串內容相等,僅適用於效能微調的特定場景。string 是參考型別,但因 不可變性 導致「修改」實為「新建」,配合 字串駐留 機制,使其行為酷似值型別。理解這兩大機制,能避免效能陷阱並撰寫更健壯的字串處理程式碼。