2009-02-02 59 views
6

StringBuilder作爲一個快速的字符串操作工具而不僅僅是串聯字符串。不管這是否是真的,我仍然想知道StringBuilder操作的結果以及它們產生的字符串。StringBuilder字符串是不可變的嗎?

Reflector中的一個簡短短語顯示StringBuilder.ToString()並不總是返回一個副本,有時它似乎返回內部字符串的一個實例。它似乎也使用一些內部函數來操縱內部字符串。

那麼,如果我這樣做,我會得到什麼?

string s = "Yo Ho Ho"; 
StringBuilder sb = new StringBuilder(s); 
string newString = sb.ToString(); 
sb.Append(" and a bottle of rum."); 
string newNewString = sb.ToString(); 

是newString和newNewString不同的字符串實例還是一樣的?我試圖通過反射器瞭解這一點,而我只是不完全瞭解所有事情。

這段代碼如何?

StringBuilder sb = new StringBuilder("Foo\n"); 
StringReader sr = new StringReader(sb.ToString()); 
string s = sr.ReadLine(); 
sb.Append("Bar\n"); 
s = sr.ReadLine(); 

最後一條語句是否返回null或「Bar」?如果它返回一個或另一個,這是定義的還是未定義的行爲?換句話說,我可以依靠它嗎?

該文檔在這個主題上非常簡潔,我不願意依賴於觀察到的行爲超過規範。

+0

請注意,自問題被回答後,StringBuilder的實現已經發生了變化。 – mayu 2016-02-16 13:13:43

回答

10

在mscorlib之外,System.String的任何實例都是不可變的,句點。

StringBuilder在內部對字符串做了一些有趣的操作,但是在一天結束時它不會返回一個字符串給你,然後以你的代碼可見的方式對它進行變異。

至於對StringBuilder.ToString()的後續調用是否返回具有相同值的String或具有相同值的不同String的同一實例,這與實現相關,您不應該依賴此行爲。

+0

是的,實驗已經證明這是真實的,但是用Reflector在內部進行探測沒有顯示明顯的原因。它似乎在每次調用中都返回對內部字符串的引用,因此我對字符串是否可能發生變化感到困惑。 – 2009-02-02 06:30:42

+0

@Mystere,StringBuilder的實現起初有點讓人望而生畏。直到我讀你的問題,並開始探索我沒有意識到他們做線程級緩存。我打算今晚(或明天)稍後再觀看。但是你可以相信所產生的字符串是不可改變的 – JaredPar 2009-02-02 06:34:02

4

newStringnewNewString是不同的字符串實例。

儘管ToString()返回當前字符串,它將清除其當前線程變量。這意味着下次您追加時,它會在追加之前獲取當前字符串的副本。

我不完全確保你在你的第二個問題得到什麼,但s將是無效的:如果在一個文件中的最後字符是上一行行終止字符(S),該行是而不是被認爲在這些字符和文件結尾之間有一個空行。之前讀取的字符串對此沒有任何影響。

+0

啊..你向我解釋了這個謎。清除線程變量是導致附加副本的原因,簡單但不明顯。我的第二個問題是關於存儲在StringReader中的引用的可變性問題的變體。 – 2009-02-02 06:41:42

2

這個類的全部目的是使字符串可變,所以它實際上是。我相信(但不是很確定)它只會返回與該對象完全沒有關係的字符串。所以經過

String s_old = "Foo"; 
StringBuilder sb = new StringBuilder(s_old); 
String s_new = sb.ToString(); 

s_old會和s_new一樣,但不會在任何其他情況下。

我應該注意到,對於Java編譯器自動將多個字符串添加到使用StringBuilder(或類似的,但更快的StringBuffer)類的操作中,我會非常驚訝。NET編譯器也不會執行此轉換。

3

newStringnewNewString 不同string實例或 一樣的嗎?我試圖找出通過反射器 ,我只是不知道一切 。

他們是不同的string實例:newString是 「Yo Ho Ho」 和newNewString爲 「Yo Ho Ho and a bottle of rum.」。 strings是不可變的,並且當您調用StringBuilder.ToString()時,此方法返回一個不可變的string,它表示當前的狀態。

會的最後一條語句返回null或 「Bar」?並且如果它返回一個或其他 其他,這是定義還是未定義 行爲?換句話說,我可以依靠 嗎?

它將返回nullStringReader正在處理您在構造函數中傳遞給它的不可變的string,因此它不受您對StringBuilder所做的任何操作的影響。

相關問題