Nullable< = vs ==比较结果

时间:2015-07-30 11:02:28

标签: c# comparison operator-keyword nullable

这种行为听起来对我不对。

DateTime? birth = null;
DateTime? death = null;

Console.WriteLine(birth == death); // true
Console.WriteLine(birth <= death); // false

为什么会这样?这非常奇怪。当然,我的意思是为什么第二个表达式也不会评估为true

编辑:

我理解以下比较会返回false,因为无法说明它们之间的关系如何:

Console.WriteLine(birth < death); // false
Console.WriteLine(birth > death); // false

这是完全可以理解的行为。但是......看看逻辑:

  • <=表示<==
  • 我们不知道如何阅读< - 可能是truefalse
  • 我们知道==true
  • 由于其中一个条件是true,其他条件不能不符合结果。这是逻辑,而不是

我的观点是 true or something else 应该是真的。

我知道C#团队就是这样设计的,但我的直觉却与众不同。既然聪明的人已经用这样的规则写了C#,我只想学习 为什么 我的直觉在这里是错误的:)

2 个答案:

答案 0 :(得分:4)

根据ECMA-334标准( 8.19 Nullable types )(强调我的):

  

比较运算符(==!=<><=>=)在操作数时具有提升形式types是非可空值的类型,结果类型是   bool。通过添加a形成比较运算符的提升形式   每个操作数类型的?修饰符(但不是结果类型)。提升==的形式    和!=    运算符认为两个空值相等,并且空值不等于非空值。提升<><=>=的形式    如果一个或两个操作数为空,则运算符返回false。

答案 1 :(得分:1)

我理解你不是在寻找规格,而是为了解释为什么以这种方式设计nullables。

为消除歧义,设计人员可以让这些运算符返回bool?值而不是bool值,如果其中一个操作数为空,则该值为null。

但是如果他们做出了这个选择,那么代码就像:

bool? comparison = birth <= death; 
if (comparison.HasValue && comparison.Value)
{
}

这有点麻烦。

作为旁注,似乎在查看IL时,C#编译器首先生成与默认值的比较,然后检查其中一个操作数是否为空,这看起来有点奇怪......

.method private hidebysig static void  Main(string[] args) cil managed
{
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> x,
           [1] valuetype [mscorlib]System.Nullable`1<int32> V_1,
           [2] valuetype [mscorlib]System.Nullable`1<int32> V_2)
  IL_0000:  ldloca.s   x
  IL_0002:  ldc.i4.1
  IL_0003:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_0008:  ldc.i4.2
  IL_0009:  newobj     instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_000e:  ldloc.0
  IL_000f:  stloc.1
  IL_0010:  stloc.2
  IL_0011:  ldloca.s   V_1
  IL_0013:  call       instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
  IL_0018:  ldloca.s   V_2
  IL_001a:  call       instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
  IL_001f:  ble.s      IL_0024
  IL_0021:  ldc.i4.0
  IL_0022:  br.s       IL_0033
  IL_0024:  ldloca.s   V_1
  IL_0026:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
  IL_002b:  ldloca.s   V_2
  IL_002d:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
  IL_0032:  and
  IL_0033:  brfalse.s  IL_003a
  IL_0035:  call       void [mscorlib]System.Console::WriteLine()
  IL_003a:  ret
} // end of method Program::Main

它也复制了静态Nullable类中已存在的逻辑。