2012-11-15 103 views
3

Possible Duplicate:
C#: Why is adding null to a string legal?這段代碼是如何得到有效的C#代碼的?

下面是有效的C#代碼:

var samsung= "xyz" + null + null + null + null + "890"; // xyz890 

這是無效的C#代碼:

var iphone= null.ToString(); // compiler error 

爲什麼以及如何的第一條語句有效,第二個是無效的?

+1

你不能改變'nothing'(這裏是null) –

+1

不知道編譯器是否刪除了空增加項?有人知道嗎? –

+2

@GrantH。如果它們是空常量,那麼是的。事實上,整個表達式在IL中簡化爲「xyz890」。 –

回答

4

+運算符用於連接字符串,並且因爲null是字符串類的實例,所以它可以用作運算符的參數。 "xyz" + null最終返回字符串「xyz」,所以此過程只是重複,直到您實際添加"890"

雖然null可以用作方法參數的字符串對象,但實際上無法調用它的方法,因爲沒有任何方法可以處理該方法調用。

將方法看作是對象處理外部請求的一種方式,而事情會更有意義。你可以發送一個請求到一個對象null作爲一個參數來處理,但你實際上不能要求null來處理一些東西。

+0

這也是很好的解釋。謝謝! –

+0

_「'null'是字符串類的一個實例...」_不,它不是一個實例。這是一個表達式,可以在某些情況下解釋爲具有「string」類型。在這種情況下,你也可以把它解釋爲'(object)null';結果是一樣的。但是空引用不是實例,它缺少實例。 –

0

因爲在任何情況下你都不能調用 null引用的方法,所以編譯器不允許它。 在第一種情況下,編譯器將預編譯字符串常量爲"xyz890",這是合法賦值。

通常,+運算符string編譯爲String.Concat(s1, s2, ...),它支持null參數。

更確切地說,在第二種情況下,實際問題不是它是空指針,而是類型將該方法綁定到。正如在其他評論中指出,你可以施放null任何引用類型和它編譯就好:

((string)null).ToString(); // compiles, but fails at run-time. 
1

C#編譯器在串連爲一個空字符串認爲無效的。

var samsung= "xyz" + null + null + null + null + "890"; 

等於

var samsung= "xyz" + ""+ ""+ ""+ ""+ "890"; 

當您嘗試調用null.toString()你基本上是試圖調用的方法的空對象,(如果編譯)總是會導致NullReferenceException上。

1

第一行是字符串。 null什麼也沒有,所以基本上你得到了xyz890。這就像做1+0+0+0+4但你的第二,你打ToString()nullnull什麼也沒有,所以沒有什麼可以撥打ToString()。您正試圖在非初始化變量上調用方法。

+0

Ohhh現在對我有意義!非常感謝:-)我的問題得到解答。 –

+0

@ user1688826如果你的問題得到解答,你應該接受一個答案 – swiftgp

+1

雖然這沒有錯,但你實際上並沒有解釋爲什麼你可以使用'operator +'將一個字符串連接到null,你可以說*你可以。運行他的代碼已經告訴他這麼多... – Servy

1

由於string是一個引用類型,null可以隱式轉換爲string。而在+運營商只是轉化爲String.Concat(obj1, obj2, obj3, ...)

爲了使你的代碼的第一案序列編譯您可以撥打Convert.ToString

var iphone = Convert.ToString(null); 
0

+運算符將被轉換爲靜態函數,看起來很像:

public static string Concat(string first, string second) {...} 

將null作爲參數傳遞給函數不是問題;它通過很好。該函數恰好在連接它們之前檢查兩個參數都不爲空;如果任何參數爲空,則將它們視爲空字符串以便不引起異常。這裏的關鍵是,在這個函數首先檢查null之前,沒有實例成員被調用。

至於null.ToString()在編譯時對任何評估值爲null的調用實例函數都會導致異常。這是該案件的定義。

+1

很好的解釋。只是一個技術細節:編寫'null.ToString()'給出編譯時錯誤:_CS0023:運算符'。'不能應用於''類型的操作數_但是,如果您對該類型有所幫助,如在'((string)null).ToString()'中,它會很好地編譯,並且您會得到'NullReferenceException' run-時間。 –

0

如果你看看IL,你會發現編譯器足夠聰明,只需刪除空值並創建一個連接字符串。如前所述,你不能做一個null.ToString();你可以做string.Empty或者分配一個字符串爲null。

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  8 (0x8) 
    .maxstack 1 
    .locals init ([0] string samsung) 
    IL_0000: nop 
    IL_0001: ldstr  "xyz890"  //null has been removed by compiler. 
    IL_0006: stloc.0 
    IL_0007: ret 
} // end of method Program::Main 

編輯
展開對尼爾森的評論。由於null表示一個零引用,所以可以公平地說,字符串concat的處理方式是C#許可,如操作。我想知道它使用的字節數組的構建,它會省略空值,因此只是使它看起來好像它是空的。

+0

我認爲原始海報問**爲什麼**這是合法的。這是一個技術細節,編譯器通過自己_compile-time_執行完整的操作(五個加法),並且只在其IL輸出中發出正確的「總和」。 –

1

你可以認爲+運營商作爲一個全局靜態函數就像這樣:

+(string leftHandSide, string rightHandSide) { 
    if (leftHandSide == null) 
    leftHandSide = string.Empty; 
    if (rightHandSide == null) 
    rightHandSide = string.Empty; 
    string returnValue; 

    // concatenate string 

    return returnValue; 
} 

由於這個字符串連接方法是靜態的它並不需要一個實例來調用它,它處理空值。但是,當您嘗試撥打ToStringnull時,沒有對象實例,因此沒有ToString方法調用,因此是例外情況。

1

這是設計。你可以閱讀C# Language Specification。報價:

String concatenation:

string operator +(string x, string y); 
string operator +(string x, object y); 
string operator +(object x, string y); 

These overloads of the binary + operator perform string concatenation. If an operand of string concatenation is null , an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object . If ToString returns null , an empty string is substituted.

[...]

所以,正如其他人所說,認爲+作爲一種方法,它接受兩個參數,並與其中的一個或兩個是null確定。