一)由於字符串是不可變的,所以具有相同字符串值的變量指向同一個字符串對象嗎?
string s = "value";
string s1 = "value";
待辦事項S和S1引用變量指向同一個字符串對象(我假設這是由於這樣的事實:string是不可改變的)? b)我意識到等式運算符(==,>等)已被重新定義以比較字符串對象的值,但在使用靜態方法比較兩個字符串時是相同的。Object.Equals()和Object.ReferenceEquals( )?
感謝名單
一)由於字符串是不可變的,所以具有相同字符串值的變量指向同一個字符串對象嗎?
string s = "value";
string s1 = "value";
待辦事項S和S1引用變量指向同一個字符串對象(我假設這是由於這樣的事實:string是不可改變的)? b)我意識到等式運算符(==,>等)已被重新定義以比較字符串對象的值,但在使用靜態方法比較兩個字符串時是相同的。Object.Equals()和Object.ReferenceEquals( )?
感謝名單
不,不是所有具有相同值的字符串都是相同的對象引用。
由編譯器生成的字符串將全部爲Interned併成爲相同的引用。在運行時生成的字符串默認情況下不會被執行,並且會是不同的引用。
var s1 = "abc";
var s2 = "abc";
var s3 = String.Join("", new[] {"a", "b", "c"});
var s4 = string.Intern(s3);
Console.WriteLine(ReferenceEquals(s1, s2)); // Returns True
Console.WriteLine(ReferenceEquals(s1, s3)); // Returns False
Console.WriteLine(s1 == s3); // Returns True
Console.WriteLine(ReferenceEquals(s1, s4)); // Returns True
注意上面,你可以強制使用String.Intern(string)
,然後允許您使用對象的平等,而不是字符串平等一些檢查,這是更快的被拘留串線。這是非常常用的一個例子是在生成的XML序列化程序代碼和名稱表中。
+1用於說明在運行時創建的字符串必須手動執行。 – ChaosPandion 2010-02-09 19:34:09
可能值得添加 var s4 = string.Intern(s3); Console.WriteLine(ReferenceEquals(s1,s4)); //返回True – Dolphin 2010-02-09 19:38:41
@Dolphin,好點,我更新了答案。 – 2010-02-09 19:41:18
是的,這些將指向相同的字符串,因爲他們都定義爲字符串文字。如果以編程方式創建字符串,則必須手動插入字符串。
這是因爲.NET框架將程序中的字符串文字實例化爲實習池。您可以使用String.Intern來檢索此引用,或者手動實習您自己的運行時生成的字符串。
詳情,請參閱docs for Intern:
因此,文字串與特定值的一個實例只存在於系統中一次。
例如,如果分配相同的文字串,以多個變量時,運行時檢索相同的參考從實習生池文字串並將其分配給各可變
但是,這是通過實施,而不是規範。 – 2010-02-09 19:33:14
正確 - 但實現確實可以做到這一點,目前,字面值。 – 2010-02-09 19:35:38
我在回答中加了一些說明。 – 2010-02-09 19:37:04
隨着當前CLR相同字面字符串指向相同的實際對象。這個過程被稱爲實際並適用於所有編譯時間字符串。
在運行時創建的字符串不是默認實現的,但可以通過調用string.Intern將其添加到實參集合中。
有關如何存儲.NET字符串的詳細說明,請參閱my answer for this question。
我不是專家,但檢查此鏈接上的字符串internment。 http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool – ChaosPandion 2010-02-09 19:27:00
另請參閱我對此的文章,瞭解其他一些註釋:http://blogs.msdn.com/ericlippert/archive/2009/09/ 28/string-interning-and-string-empty.aspx – 2010-02-09 19:35:25
@Eric - 非常棒的閱讀,感謝您發佈該鏈接。 – ChaosPandion 2010-02-09 19:41:24