2011-06-24 42 views
11

是否安全,改寫下面的代碼:重寫HasValue的??運營商

bool b = foo.bar.HasValue ? foo.bar.Value : false; 

bool b = foo.bar.Value ?? false; 

其中bar是可空類型bool?

回答

23

最簡單的修復有

bool b = foo.bar.GetValueOrDefault(); 

這也實際上比.Value便宜,因爲它省略了具有價值的檢查。它將默認爲default(T),這裏確實是false(它只是返回底層T字段的值,根本沒有任何檢查)。

如果你需要一個不同的默認爲default(T),則:

var value = yourNullable.GetValueOrDefault(yourPreferredValue); 
+1

每天學習新東西。不知道我用了多少次'Nullable '而只是不知道這些方法。 – shambulator

+0

優秀的答案。 –

6

沒有 - 這是不是安全的。

行:

bool b = foo.bar.Value ?? false; 

將引發InvalidOperationException如果foo.bar沒有價值。

而是使用

var b = foo.bar ?? false; 

更新 - 我剛剛瞭解.GetValueOrDefault();從其他的答案 - 這看起來像一個很好的建議使用!


更新2 - @ ProgrammingHero的答案也是正確的(+1加入!) - 行:

bool b = foo.bar.Value ?? false 

實際上不會編譯 - 因爲Error 50 Operator '??' cannot be applied to operands of type 'bool' and 'bool'

+0

'foo.bar'的類型是'bool?',但'foo.bar.Value'只是'bool',這就是您應該使用'??'的原因。運算符僅限於'foo.bar' - 它具有正確的類型。記住'??'用您指定的需要可爲空或引用類型的值替換null,而bool只是一個值類型。 – Matt

2

ffoo.bar ?? false會更安全的使用

9

你想要的是:

bool b = foo.bar ?? false; 

這是(奇怪)安全的空合併運算符的用途。

的??操作者被稱爲空合併運算符和用於定義要空值類型的默認值以及引用類型。如果它不是null,則返回左邊的操作數;否則它返回右操作數。

來源:http://msdn.microsoft.com/en-us/library/ms173224.aspx

Nullable<T>的情況下,在功能上等同於Nullable<T>.GetValueOrDefault(T defaultValue)

代碼:

bool b = foo.bar.Value ?? false; 

將導致一個編譯器錯誤,因爲你不能操作適用於值類型和Nullable<T>.Value始終返回值類型(或拋出時,有沒有價值除外) 。

+0

+1發現「不會編譯」 - 雖然我不同意關於「令人驚訝的」 - 主要是因爲99%的時間我發現自己使用它的值類型:) – Stuart

+1

很多人都很驚訝,因爲null-取決於您是否正在處理參考,合併更改。對於引用類型,IL等價於'x == null? x:false;'。對於'可爲空',??被替換爲對'GetValueOrDefault(T);'的調用。驚喜! –

+0

與當前標記爲回答的答覆一樣有用,我覺得這個回答是OP問題的實際答案。 – Sameer

0

foo.bar.Value表示有一個的非空值,,如果沒有實際值則拋出InvalidOperationException

2
bar.Value ?? false 

有編譯錯誤,因爲左操作的?運算符應該是引用或可爲空類型。

1

也許你看看Stackoverflow中的this文章 - 這是一個優雅的空檢查風格obj.IfNotNull(lambdaExpression) - 如果obj不爲null,則返回所需的對象,否則僅爲null(但不會拋出異常)。

如果您正在訪問引用的實體,例如我使用它與實體框架。

var str=Entity1.Entity2.IfNotNull(x=>x.EntityDescription) ?? string.Empty 

它返回包含在Entity2其通過引用Entity1EntityDescription - 或空字符串如果任何對象Entity1Entity2null。沒有IfNotNull,你會得到一個長而醜陋的表情。

擴展方法IfNotNull定義有如下:

public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f) 
    where TIn : class 
    where TOut: class 
{ 
    if (v == null) return null; else return f(v); 
} 

更新: 如果更新代碼C#6.0版(.NET框架4.6 - 但seems to support older frameworks 4.x too)有一個新的操作員可以使這項任務變得簡單:「elvis」操作員?.

其工作原理如下:

var str=(Entity1.Entity2?.EntityDescription) ?? string.Empty 

在這種情況下,如果Entity2null,評估停止,(...)成爲null - 在?? string.empty部分由string.Empty取代null之後。換句話說,它的工作方式與.IfNotNull(...)相同。