首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# string 參考型別卻表現像值型別:字串駐留與不可變性深度解析

     編輯:關於C#

現象重現

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):

  1. 編譯期常值字串 (ldstr IL 指令) 自動駐留。
  2. 執行期呼叫 string.Intern() 可手動駐留。
  3. String.Equals 靜態多載會先比較參考相等,極大提升常見字串比較效能。

Equals 三種多載行為差異

多載行為用途
Equals(object)虛方法,內部呼叫 CompareOrdinal 逐字元比較多型比較
Equals(string)強型別版本,同樣逐字元比較避免裝箱
Equals(string, string)靜態方法,先比參考相等,相等即回傳 true,否則逐字元比較高效能比較首選

實務建議

  • 大量字串拼接請用 StringBuilder 或 string.Create (高效能場景)。
  • 比較字串優先用 string.Equals(a, b, StringComparison.Ordinal) 或 == (已針對駐留優化)。
  • 不可序列化、需頻繁修改的字串資料,考慮 char[] 或 Span<char>。
  • 切勿依賴 ReferenceEquals 判斷字串內容相等,僅適用於效能微調的特定場景。

總結

string 是參考型別,但因 不可變性 導致「修改」實為「新建」,配合 字串駐留 機制,使其行為酷似值型別。理解這兩大機制,能避免效能陷阱並撰寫更健壯的字串處理程式碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved