2013-02-22 65 views
5

我有以下的C#代碼:創建了多少個字符串對象?

string stg1 = "String 1"; 
string stg2 = "String 2"; 
string stg3 = "String 3"; 
string stg4; 
stg4 = stg1 + stg3; 
stg4 = stg4 + stg2 + stg3; 
stg4 = ""; 
stg3 = ""; 

有多少人創建的字符串對象?
我想創建7個字符串對象:"String 1""String 2""String 3"stg1 + stg3stg4 + stg2 + stg3""""。我不確定第4條語句(string stg4;)是否創建了一個字符串對象,並且我在某處讀取了分配字符串的空字符串""未創建對象,但我不認爲這是真的。你們有什麼感想?

+1

一個字符串只創建一次,所以'string.Empty'都會引用實習池中的同一個字符串。 http://msdn.microsoft.com/en-us/library/system.string.intern.aspx – 2013-02-22 23:59:42

+2

@StevenBakhtiari重要嗎? – Servy 2013-02-23 00:17:39

回答

11

我讀了一個地方,指定一個空字符串「」不創建一個對象,但我不認爲這是真的。你們有什麼感想?

這並不完全正確。絕對有一個爲空字符串創建的字符串實例。

話雖如此,代碼中不會有兩個實例;只會有一個。除非在編譯時禁用該設置,否則編譯器將查找所有編譯時間文字字符串相同,並只創建一個對象來表示該對象,並將所有定義該字符串的變量賦予與該字符串相同的引用。這被稱爲「實習」。

請注意,默認情況下,字符串實際上只在編譯時間字符串中完成,而不是在運行時生成的字符串。如果在運行時生成兩個相等的字符串,它們不一定是對相同字符串對象的引用。

除此之外,你的分析是正確的。

同樣值得注意的是,當你正確地指出stg4 + stg2 + stg3只會創建一個字符串時,你並沒有真正解釋原因,也不明白爲什麼會這樣。

最初的猜測可能是在這裏執行了兩個操作,第一個是stg4 + stg2,這將導致一個字符串,然後將該結果連接到stg3以創建最終結果。但情況並非如此。編譯器將實際上產生調用string.Concat,通過在所有三個字符串作爲參數(Concat被定義爲Concat(params string[] args),因此它可以接受任何數量的字符串)和Concat足夠聰明,只創建一個字符串,而不是爲n-1箇中間值創建字符串。

+0

[MSDN](http://msdn.microsoft.com/en-us/library/system.string.intern.aspx):_「內部池,它包含對每個唯一的文字字符串的唯一引用**或以編程方式在您的程序中創建**「_ – 2013-02-23 00:12:59

+3

@TimSchmelter:以編程方式創建的字符串不會自動實現; 'object.ReferenceEquals(「AB」,String.Concat(「A」,「B」))''爲'false'。這就是[Intern](http://msdn.microsoft.com/zh-cn/library/system.string.intern.aspx)方法的用途。 – 2013-02-23 00:14:46

+1

@TimSchmelter它可以*實現以編程方式創建的字符串,這就是爲什麼該語句存在的原因,但默認情況下未啓用。同樣,您可以選擇不實習編譯時間文字字符串。請注意,'string.Intern'的*目的是爲了在運行時創建一個字符串。如果在運行時創建的所有字符串都始終被執行,那麼這樣的方法就沒有用處。 – Servy 2013-02-23 00:16:55

6

塞維的答案是非常重要的;我特別喜歡對連接的正確分析。

我只是簡單地將這個優秀的答案加入一個小的附加點,那就是它是實現定義的,是否非文字String.Empty被字面值""限制。一些版本的.NET可以,有些不會自動插入。

詳情請參閱

http://ericlippert.com/2009/09/28/string-interning-and-string-empty/