2017-06-18 32 views
1

我想了解空條件運算符。從書中我學到了,例如,如果我將string []數組傳遞給方法,我可以不使用條件作用域,而使用null條件運算符來檢查傳遞的字符串[]數組是否爲空,因爲例如在方法中,我會希望使用.Length屬性,如果我將null傳遞給它,它將導致運行時錯誤。空條件運算符與方法.Value可空結構

所有這一切我明白,但是當我想用泛型Nullable結構中的可爲null的int和.Value屬性來使用它時,它已經向我拋出了編譯器錯誤。

我想問題會是,我不明白這是什麼'?'在後綴變量之後做空。我認爲它只是跳過它後面的屬性或方法,但它可能會傳遞null並只隱藏異常。我真的不知道,所以我想問一下這個空條件運算符究竟做了些什麼,爲什麼這個可爲空的int例子會導致錯誤。

代碼與錯誤:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string text = null; 
     Console.WriteLine("Variable contains: {0}", text?.Length); //All OK 

     int? nullableInt = null; 
     Console.WriteLine("Variable contains: {0}", nullableInt?.Value); //Compiler error 

     Console.ReadLine(); 
    } 
} 

編輯: CompilerError消息:

'INT' 不包含 '價值' 和沒有擴展方法 '值' 接受第一個參數的定義可以找到'int'類型(是否缺少使用指令或程序集引用?)

編輯2: 這篇文章是重複的: null conditional operator not working with nullable types? 但是我無法從這篇文章理解的問題,但我設法得到它從感謝@adjan https://stackoverflow.com/a/44613674/7477611 張貼在那裏,他解釋得很好,但在我的努力procces學習它,我爲稍後閱讀此文的人提供了一個更好的解釋,也許對於那些與我處於同一位置的人有更好的解釋。如果在可空類型上使用'?'運算符,例如int?.Member(Member - 某個方法,屬性...),那麼如果變量爲null,它將跳過成員,但是如果它具有例如5 ,那麼運算符'?'返回variable.GetValueOrDefault(),它只返回int值。 (返回基本類型的Nullable),這幾乎是@adjan所說的。但是,我將在這裏展示的代碼,對我解釋了一切:

static void Main(string[] args) 
    { 
     int? number = null; 

     variable?.Member 

     // in fact operator '?' is doing folowing: 
     if (number.HasValue) 
     { 
      Console.WriteLine(number.GetValueOrDefault().GetType()); //System.Int32 
     } 
     else 
     { 
      Console.WriteLine(number); //null 
     } 
    } 

正如你可以看到number.GetValueOrDefault()返回System.Int32數據類型,如果你想使用.Value屬性它必須是空類型,並且System.Int32不是可以爲空的類型,因此它沒有訪問.Value成員。這就是它導致錯誤的原因。

希望它有幫助:) 謝謝你的回答。 :)

+0

你應該總是在你的問題中包含完整的錯誤信息 – UnholySheep

+3

[null條件運算符不可用於可空類型?](https://stackoverflow.com/questions/31811392/null-conditional-operator-not-使用可空類型) – mjwills

回答

5

上的空類型值類型Tvariable?.Member實際上轉換到一個功能大致是

if (variable.HasValue) 
    return variable.GetValueOrDefault().Member; 
else 
    return null; 

variable.GetValueOrDefault()是類型T的,不Nullable<T>。只有Nullable<T>有一個成員Value(除非它是你自己的結構,包含一個成員Value,但例如int從你的代碼不)。

+0

是的,記住這個東西只是一個語法糖,並且看看它實際生成的代碼總是很好。 –

0

在您的代碼中,您正在嘗試訪問nullableInt的成員Value,但由於此成員不存在,因此無法編譯此代碼。

?.操作員是訪問者。如果訪問的成員存在並且未設置或設置爲null,則它在運行時返回null。相比之下,在這種情況下,標準訪問者(。)將引發Null reference exception

嘗試用nullableInt ?? 0之類的東西代替您的代碼。 ??是空合併運算符並將用空字符串替換null。

+0

@mjwills是的,它是'nullableInt? 0',因爲它是一個int值。或'nullableInt?.ToString()??「」''如果你想要一個字符串 – Jimbot

+0

它會引發一個錯誤,你必須做'nullableInt?.ToString()'所以它返回null。 – Jimbot

+0

是的只是嘗試它:'int? nullableInt = null; Console.WriteLine(「Variable contains:{0}」,nullableInt?.ToString()??「this is null」);' – Jimbot

0

可爲空的值類型是特殊類型。當您使用nullableInt?時,您的結果實際上是類型int,它沒有Value屬性。

空條件運算符只對參考類型有意義,對於string作爲不可變引用類型的特例。

+0

爲什麼?你可以有一個可爲空的結構體,併爲結構體的成員使用空值條件運算符。 – Adrian

+0

謝謝,還有一個問題,這是什麼結果的int類型與nullableInt? –

+0

@adjan真的,我忘了結構。是的,儘管我會避免可空結構,你是對的。 –

0

下面的代碼說明了此問題:

string[] temp = null; 
int cc = -1; 
if (temp == null) 
{ 
    cc = 0; 
} 
else 
{ 
    cc = temp.Count(); 
} 

有一個空的陣列之間的差(計數()= 0)和陣列,其爲空。

您的代碼就變成了:

Console.WriteLine("Variable contains: {0}", args?.Count() ?? 0); //All OK 
Console.WriteLine("Variable contains: {0}", nullableInt?.ToString() ?? "woops"); //now ok 
1
nullableInt?.Something 

是語法糖:

nullableInt is null ? null : nullableInt.Value.Something 

因此沒有必要把.value的存在。因爲如果你這樣做,你是切實做好nullableInt.Value.Value

等效代碼什麼通過nullableInt?.Value要的是nullableInt(本身)。

參見:

null conditional operator not working with nullable types?