Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可为空<;=vs==比较结果_C#_Comparison_Operator Keyword_Nullable - Fatal编程技术网

C# 可为空<;=vs==比较结果

C# 可为空<;=vs==比较结果,c#,comparison,operator-keyword,nullable,C#,Comparison,Operator Keyword,Nullable,我觉得这种行为是不对的 DateTime? birth = null; DateTime? death = null; Console.WriteLine(birth == death); // true Console.WriteLine(birth <= death); // false 这是完全可以理解的行为。但是看看逻辑: 根据ECMA-334标准(8.19可空类型)(强调矿山): 比较运算符(=,!=,,=)在操作数类型均为不可空值类型且结果类型为空时具有提升形式 bool

我觉得这种行为是不对的

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

Console.WriteLine(birth == death); // true
Console.WriteLine(birth <= death); // false
这是完全可以理解的行为。但是看看逻辑:


  • 根据ECMA-334标准(8.19可空类型)(强调矿山):

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


    我理解你不是在寻找规范,而是在寻找一个解释为什么nullables是这样设计的

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

    但如果他们做出了这个选择,代码将如下所示:

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

    bool?比较=出生你是在问为什么语言是这样设计的,还是想证明你看到的行为符合语言?@JonSkeet为什么语言是这样设计的:)我只是不明白为什么它会这样做……在这种情况下,false意味着“未知”。设计者可能已经实现了比较运算符(不包括==和!=),以便它们返回一个可为空的布尔结果,而不是布尔结果,但是使用它们的代码的可读性显然会受到影响。我想他们更喜欢用这种方式实现它,尽管可能会有一些角落案例被清楚地记录在案。@vc74请参见编辑:)@Randolph birthdeath返回false,因为其中一个变量为null。“birth=DateTime.Now”的结果将为false
    
    bool? comparison = birth <= death; 
    if (comparison.HasValue && comparison.Value)
    {
    }
    
    .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