2010-02-09 38 views
16

一)由於字符串是不可變的,所以具有相同字符串值的變量指向同一個字符串對象嗎?

 string s = "value"; 
     string s1 = "value"; 

待辦事項S和S1引用變量指向同一個字符串對象(我假設這是由於這樣的事實:string是不可改變的)? b)我意識到等式運算符(==,>等)已被重新定義以比較字符串對象的值,但在使用靜態方法比較兩個字符串時是相同的。Object.Equals()和Object.ReferenceEquals( )?

感謝名單

+2

我不是專家,但檢查此鏈接上的字符串internment。 http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool – ChaosPandion 2010-02-09 19:27:00

+10

另請參閱我對此的文章,瞭解其他一些註釋:http://blogs.msdn.com/ericlippert/archive/2009/09/ 28/string-interning-and-string-empty.aspx – 2010-02-09 19:35:25

+0

@Eric - 非常棒的閱讀,感謝您發佈該鏈接。 – ChaosPandion 2010-02-09 19:41:24

回答

21

不,不是所有具有相同值的字符串都是相同的對象引用。

由編譯器生成的字符串將全部爲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

+1用於說明在運行時創建的字符串必須手動執行。 – ChaosPandion 2010-02-09 19:34:09

+0

可能值得添加 var s4 = string.Intern(s3); Console.WriteLine(ReferenceEquals(s1,s4)); //返回True – Dolphin 2010-02-09 19:38:41

+0

@Dolphin,好點,我更新了答案。 – 2010-02-09 19:41:18

3

是的,這些將指向相同的字符串,因爲他們都定義爲字符串文字。如果以編程方式創建字符串,則必須手動插入字符串。

這是因爲.NET框架將程序中的字符串文字實例化爲實習池。您可以使用String.Intern來檢索此引用,或者手動實習您自己的運行時生成的字符串。

詳情,請參閱docs for Intern

因此,文字串與特定值的一個實例只存在於系統中一次。

例如,如果分配相同的文字串,以多個變量時,運行時檢索相同的參考從實習生池文字串並將其分配給各可變

+2

但是,這是通過實施,而不是規範。 – 2010-02-09 19:33:14

+0

正確 - 但實現確實可以做到這一點,目前,字面值。 – 2010-02-09 19:35:38

+0

我在回答中加了一些說明。 – 2010-02-09 19:37:04

2

隨着當前CLR相同字面字符串指向相同的實際對象。這個過程被稱爲實際並適用於所有編譯時間字符串。

在運行時創建的字符串不是默認實現的,但可以通過調用string.Intern將其添加到實參集合中。

有關如何存儲.NET字符串的詳細說明,請參閱my answer for this question

相關問題