2017-05-31 53 views
24

我以爲T?只是Nullable<T>的編譯速記。根據MSDN爲什麼不可能在可空行情下調用靜態方法?

語法T?Nullable<T>,其中T是值類型的簡寫。 這兩種形式是可以互換的。

但是,有一點(不顯着)的區別:Visual Studio中不允許我打電話給在速記靜態方法:

bool b1 = Nullable<int>.Equals(1, 2); //no error 
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'" 

爲什麼?這種限制是否有任何理由?

+1

這是一個語法的東西。解析器找不到'?.' – jwg

+2

這是一個很好的問題,雖然我不知道那會是什麼意思,我們會用Nullable .Equals(1,2)來測試什麼? (我不是故意的,是一個真正的問題) – hardkoded

+2

從C#6開始,'?。'用作空條件檢查,因此它是語法錯誤。當使用早期版本不能識別單個運算符時,情況可能會有所不同。 –

回答

12

你的MSDN報價相呼應的C#5.0規範的§4.1.10:

可空類型寫入T?,其中T是基礎類型。此語法是System.Nullable<T>的簡寫,並且這兩種形式可以互換使用。

但「可互換」是過分簡單化。確實,T?表示System.Nullable<T>,但正如您發現的那樣,您無法在任何地方使用T?System.Nullable<T>。特別地,種在您的示例成員訪問(§7.6.4)需要簡單名稱(第7.6.2節):

[第7.6節]基本表達式包括最簡單的形式的表達。

基本表達式:
初級無陣列創建表達式
陣列創建表達式

初級無陣列創建表達式
文字
簡單名稱
括號的表達
成員訪問
...

[第7.6節。2] A 簡單名稱是任一形式的I或形式I<A1, ..., AK>,其中I是單個標識符和<A1, ..., AK>是可選類型參數列表的。

[§7.6.4]甲成員訪問要麼形式E.I或形式E.I<A1, ..., AK>,其中E基本表達式的,I是單個標識符和<A1, ..., AK>是可選類型-argument-list

Nullable<T>簡單名稱T?是沒有,所以前者的編譯,而後者則沒有。

爲什麼C#語言的設計者需要成員訪問表達式中使用簡單名稱而不是任何類型?我想只有他們可以肯定地說,但也許這個要求簡化了語法:在一個表達式中,編譯器可以假定?始終是條件(三元)運算符,而不是可能的可空類型說明符。

事後看來,這是一個幸運的選擇,它允許C#6.0在不打破現有程序的情況下添加?.運算符。例如,考慮這種病理例如:

struct S 
{ 
    public bool Equals(int x, int y) { return false; } 
} 

class C 
{ 
    public static void Main() 
    { 
     S? S = new S(); 
     Console.WriteLine(S?.Equals(1, 1)); // "True" or "False"? 
    } 
} 

應該S?.Equals被解析爲Nullable<S> . Equals,以Object類的Equals靜態方法的調用?或者應該將其解析爲S ?. Equals,對Equals變量S的實例方法的空條件調用?因爲S?不是簡單名稱,它是明確的後者。

0

雖然您對語法正確,但可以使用Nullable類型作爲參數從默認類型調用Equals方法。

你可以嘗試用你想要的任何值這個單元測試:

int? i = 4; 
int? j = null; 
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j)); 
+0

這是因爲這兩個方法調用只是調用了'object.Equals',它需要兩個'object'實例。這些與'object.Equals'完全相同。 – Servy

+0

你說得對。我只是指出,沒有必要嘗試調用'int?.Equals()'。 – Aboc

相關問題