HasValue和Value

时间:2015-03-09 22:41:01

标签: c#

我在代码审查中注意到了一些问题,我想知道它是否合适。

a.EndDate.HasValue && a.EndDate > paymentPeriodEndDate

不应该是:

a.EndDate.HasValue && a.EndDate.Value > paymentPeriodEndDate

注意,a.EndDate是DateTime?,而paymentPeriodEndDate是DateTime

应该使用.Value吗?或者可以省略它。编译器允许它,并且代码可以工作。然后我想知道为什么有.Value可用。

3 个答案:

答案 0 :(得分:14)

Nullable可以隐式地转换为它的基础类型,所以

a.EndDate > paymentPeriodEndDate

隐式转换为

((DateTime)a.EndDate) > paymentPeriodEndDate

.Value作为演员阵容的一部分 由于您已经进行了空检查,因此没有实际区别。

  

然后我想知道为什么有.Value可用。

当编译器无法隐式知道预期输出是什么时(例如,传递给泛型方法或带有重载的方法时),您将使用Value。由于您要与另一个DateTime进行比较,编译器可以推断出您的意图并为您致电.Value


* 技术上我认为编译器添加了一个演员,因为从Nullable<T>T的演员运算符是explicit,但原则应该是是一样的。

答案 1 :(得分:4)

我在这里只使用a.EndDate > paymentPeriodEndDate,因为您的代码被解释为

a.EndDate.HasValue && a.EndDate > (DateTime?)paymentPeriodEndDate

你在这里拥有的是一个提升的运营商:

  
      
  • 对于关系运算符

    <  >  <=  >= 
    
         

    如果操作数类型都是非可空值类型且结果类型为bool,则存在提升形式的运算符。通过向每个操作数类型添加单个?修饰符来构造提升形式。如果一个或两个操作数为空,则提升的运算符将生成值false。否则,提升的运算符将解包操作数并应用基础运算符以生成bool结果。

  •   

结果,你有这个:

a.EndDate.HasValue && a.EndDate.HasValue && a.EndDate.GetValueOrDefault() > paymentPeriodEndDate

所以,你实际上在这里仔细检查a.EndDate.HasValue

答案 2 :(得分:2)

您可以省略.Value,因为如果a.EndDate没有值,则比较将始终返回false

但是在您的代码中,您检查它是否具有值,因此可以安全地假设,该比较将返回确切的结果,而不是来自一个没有值的参数的false

就生成的IL代码而言,它们可能几乎完全相同,因此不会出现性能损失或涉及此类内容。