将HasValue重写为??运营商

时间:2011-06-24 11:15:48

标签: c# nullable

重写以下代码是否安全:

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

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

其中bar是可空类型bool?

8 个答案:

答案 0 :(得分:25)

最容易解决的问题是

bool b = foo.bar.GetValueOrDefault();

实际上也比.Value便宜,因为它省略了有效值检查。它将默认为default(T),这里确实是false(它只返回基础T字段的值,而不进行任何检查。

如果您需要与default(T)不同的默认值,则:

var value = yourNullable.GetValueOrDefault(yourPreferredValue);

答案 1 :(得分:12)

你想要的是:

bool b = foo.bar ?? false;

这是(令人惊讶的)安全性和无效合并运算符的预期用途。

  

?? operator被称为null-coalescing运算符,用于定义可空值类型的默认值以及引用类型。如果它不为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始终返回值类型(或在没有值时抛出异常)。

答案 2 :(得分:7)

不 - 这不安全。

该行:

bool b = foo.bar.Value ?? false;
如果foo.bar没有值,

将抛出InvalidOperationException。

改为使用

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'

答案 3 :(得分:2)

不。

  

Value属性返回值if   一个被分配,否则一个   System.InvalidOperationException是   抛出。

来自:http://msdn.microsoft.com/en-us/library/1t3y8s4s%28v=vs.80%29.aspx

因此,如果hasValue为false,那么当您尝试运行它时,您将在第二个中抛出异常。

答案 4 :(得分:2)

ffoo.bar ?? false使用

会更安全

答案 5 :(得分:2)

bar.Value ?? false

有编译错误,因为左操作数?运算符应该是引用或可空类型。

答案 6 :(得分:1)

也许您也可以查看Stackoverflow中的this文章 - 它是样式obj.IfNotNull(lambdaExpression)中的优雅空检查 - 如果obj不为null则返回您想要的对象,否则只返回null(但没有抛出异常)。

如果您正在访问引用的实体,我将它与实体框架一起使用,例如

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

返回EntityDescription中包含的Entity2 Entity1,如果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 Framework 4.6 - 但是seems to support older frameworks 4.x too),则可以使用新的运算符来简化此任务:“elvis”运算符 ?.

它的工作原理如下:

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

在这种情况下,如果Entity2null,则评估停止,(...)变为null - 之后?? string.empty部分将取代nullstring.Empty。换句话说,它的工作方式与.IfNotNull(...)的工作方式相同。

答案 7 :(得分:0)

foo.bar.Value表示有一个值时的非可空值,,如果没有实际值则抛出InvalidOperationException