2013-02-21 44 views
4

我有示例代碼。在C#中賦值和創建字符串實例有什麼區別?

var charMass = new char[] { 's', 't', 'r' }; 
string myString = new string(charMass); 
string myString2 = new string(charMass); 
string myString3 = "str"; 
string myString4 = "str"; 

bool bb1 = Object.ReferenceEquals(myString, myString2); 
bool bb2 = Object.ReferenceEquals(myString, myString3); 
bool bb3 = Object.ReferenceEquals(myString3, myString4); 

爲什麼bb1和bb2是假的?我知道equals必須顯示爲真,因爲它比較值,但對於這些字符串的內存分配情況如何?爲什麼myString3和myString4指向堆中的同一塊內存,但myString和myString2不是?

+0

http://stackoverflow.com/questions/4232789/why-does-referenceequalss1-s2-returns-true 也許上面的鏈接可以幫助你。 – 2013-02-21 10:10:19

+0

這[文章](http://en.wikipedia.org/wiki/String_interning)可以解釋你的問題。 – 2013-02-21 10:15:11

回答

5

C#編譯器優化它,以便相同的文字指向相同的字符串實例

MSDN

實習生池節省字符串存儲。 如果分配字面 字符串常量幾個變量,每個變量被設置爲參考 相同的恆定在實習生池而非 引用具有相同 值字符串的幾個不同的實例。

+0

我認爲myString和myString2也必須被實施,並引用同一個實習對象。感謝您的鏈接。 – 2013-02-21 10:28:14

+0

實習生池是某種哈希表的,關鍵是一個字符串值,值是堆到字符串的引用,對不對? – 2013-02-21 10:40:03

0

也許編譯器以某種方式優化"str"成單個字面,它然後分配給每個可變,當然,被串指針,意味着它們都指向相同的地址。

+1

編譯器不會優化*變量*。它優化*文字*;生成兩個相同的文字,以指向元數據字符串表中的相同位置。 – 2013-02-22 15:24:40

+0

感謝Eric的更正。 – 2013-02-22 15:30:45

1

myStringmyString2由於您明確調用了字符串構造函數,因此每次都會創建一個新對象,因此它們永遠都不會彼此引用相等(或任何其他字符串)。很明顯,這個新對象不會被引用 - 等於任何其他已經存在的對象。

myString3myString4是基準相等,因爲編譯器interns the strings:最終會被在運行時對同一個對象的引用在編譯時與字符串文字初始化字符串值:

公共語言運行時節省由字符串存儲維護名爲實習生池的 表,其中包含對 的單個引用,每個唯一的文字字符串在 程序中以編程方式聲明或創建。因此,具有 特定值的文字字符串的實例僅在系統中存在一次。

例如,如果您分配相同的文字串幾個 變量,運行時獲取相同的參考,從實習生池的文字 字符串,並將其分配給每個變量。

0

這是基於框架中字符串的底層實現。

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

我看到它的方式是,在MyString和myString2,你創建的那些使用char []並沒有在實習生池正在創建的字符串默認查找。

在myString3和myString4的情況下, myString3爲InternPool和myString4添加了值,您剛剛獲得了參考,因爲它是樣本塊。

我以前的印象是,在框架IsIntern的早期版本是可選的,讓開發商來。看起來這是不一定的情況下

4

我回答你的問題在這裏:

http://blogs.msdn.com/b/ericlippert/archive/2009/09/28/string-interning-and-string-empty.aspx

簡短的回答是:實習字面字符串是廉價和容易,因此默認情況下完成。實習動態分配的字符串通常在一個巨大的時間量的成本節約字節數小,因此是不值得理會。如果你想強迫實習,你可以自己做。

+0

對於包含字符串值作爲鍵的interned字符串的內部哈希表,以及對堆中字符串的引用呢? Richter在他的書中告訴了這件事,這是否是一種不可觸及的存儲空間,直到應用程序域被卸載爲止?我仍然不清楚。 – 2013-02-22 15:21:00

+0

@IgorLozovsky:我不明白你在這裏問的問題。你問的是如何實現String.Intern? – 2013-02-22 15:23:40

+0

CLR在每個進程的基礎上維護一個字符串散列表。在這個過程中,它們在所有應用程序域中共享。我在Jeffrey Richter的書中找到了這個信息。 – 2013-02-22 16:01:59

相關問題