2013-06-27 99 views
21

請幫助理解這種行爲。當我使用這個:編譯時的C#連接字符串

bool a1 = (object)("string" + 1) == ("string" + 1); 

結果是false

但是,當我使用這個

bool a2 = (object)("string" + "1") == ("string" + "1"); 

結果是true

那麼,爲什麼a1 != a2

+0

我不知道爲什麼,但我知道你不應該使用檢查字符串的質量「==」反正。 object1.equals(object2)是這樣做的方式,至少在我的理解。我沒有發佈這個答案,因爲它可能不會回答你的問題。 –

+0

檢查此:http://stackoverflow.com/questions/3398604/string-string-int-whats-behind-the-scene-c – Ani

+1

@Ricky Mutschlechner:AFAIK運算符'=='=='.equals'。 ;-) –

回答

34

鑄造到object強制引用相等比較。

在第一種情況下,會在運行時生成兩個不同的string對象。由於它們是不同的實例,所以結果是錯誤的。

在第二種情況下,編譯器注意到"string" + "1"總是會變爲"string1"並實施該字符串並在兩個地方使用相同的引用。由於它是相同的字符串引用,所以結果是正確的。

+2

@OP只需要添加,你應該總是比較字符串與String.Equals – Mataniko

+0

+1。我喜歡這個答案。謝謝:) –

+10

@Mataniko不,你應該確保你的變量是編譯時類型的字符串,如果你使用'operator =='。只有當一個或多個對象沒有靜態類型爲'string'時(這應該是非常罕見的),才使用'string.Equals'。 – Servy

19

有這裏發生了兩個重要的事情:

首先,表達"string" + 1在運行時間,而"string" + "1"是在編譯時進行計算評估。

其次,您正在使用參考比較。運行時生成的字符串實際上引用不同的對象,而編譯時生成的字符串引用相同的對象,因此第一個表達式爲false,第二個表達式爲true

如果你感興趣,生成的IL是:

// bool a1 = (object)("string" + 1) == ("string" + 1); 
// bool a2 = (object)("string" + "1") == ("string" + "1"); 

IL_0000: ldstr  "string" 
IL_0005: ldc.i4.1  
IL_0006: box   System.Int32 
IL_000B: call  System.String.Concat 
IL_0010: ldstr  "string" 
IL_0015: ldc.i4.1  
IL_0016: box   System.Int32 
IL_001B: call  System.String.Concat 
IL_0020: ceq   
IL_0022: stloc.0  // a1 
IL_0023: ldstr  "string1" 
IL_0028: ldstr  "string1" 
IL_002D: ceq   
IL_002F: stloc.1  // a2 
+3

發佈IL的+1:P –

+0

整潔。注意提及如何看待IL這樣的? – kenchilada

+1

@radium我個人使用[ILSpy](http://ilspy.net/)。 –