【问题标题】:Why does >= return false when == returns true for null values?为什么当 == 为空值返回 true 时 >= 返回 false?
【发布时间】:2011-05-22 22:41:01
【问题描述】:

我有两个 int 类型的变量? (或 Nullable 如果你愿意)。我想对两个变量进行大于或等于 (>=) 比较,但事实证明,如果两个变量都为 null,则返回 false,而 == 运算符显然返回 true。

有人可以向我解释为什么这是合乎逻辑的,因为 >= 运算符的语义定义包含单词“或”吗?

【问题讨论】:

  • 你能发布产生这种奇怪行为的代码吗?
  • 实际上,我会质疑 == 返回 true 是否合适。我认为这根本不合适。如何证明两个值未知的变量相等?
  • @Charles,因为如果它们是相同的空类型(例如int?),那么它们的值是已知的。 null.
  • @moo-juice,不在我的世界里......如果你的名字是空的,你会回答吗? null 与“null”不同。有一部老电影叫《我叫Nobody》(《谁打碎了玻璃,孩子们?》——“Nobody”)那么“Nobody”是谁?在现实世界中,(代码内部之外),null 表示该值是未知的......数据结构值可能是已知的(它是Null),但变量存在的真正问题域实体/值代表未知..
  • @Charles,喜欢这个比喻!。但是谁没有打破玻璃?

标签: c# comparison operators nullable


【解决方案1】:

由于默认情况下int 不能为空并且其值将设置为0,因此为int 类型构建的> 和values 一起使用而不是@ 987654326@.

请参阅我对类似问题的回答,其中我写了一些使用less < 和greater > 运算符https://stackoverflow.com/a/51507612/7003760 处理nullable int 的方法

【讨论】:

    【解决方案2】:

    当这个功能最初是在 C# 2.0 中设计的时,关于这个奇怪的地方存在巨大的争论。问题是 C# 用户已经完全习惯了这种意义:

    if(someReference == null)
    

    将相等性扩展到可空值类型时,您有以下选择。

    1. 可空相等性真正解除。如果一个或两个操作数为空,则结果既不是真也不是假,而是空。在这种情况下,您可以:

      • a) 在 if 语句中具有可空值类型相等是非法的,因为 if 语句需要一个布尔值,而不是一个可空布尔值。相反,如果他们想与 null 进行比较,则要求每个人都使用 HasValue。这既冗长又令人恼火。

      • b) 自动将 null 转换为 false。这样做的缺点是,如果 x 为 null,x==null 会返回 false,这会造成混淆,并且不利于人们对 null 与引用类型进行比较的理解。

    2. 不解除可空相等性。可空相等是真或假,与空的比较是空检查。这使得可空相等与可空不等式不一致。

    这些选择显然都不正确;他们都有优点和缺点。例如,VBScript 选择 1b。经过多次辩论,C# 设计团队选择了#2。

    【讨论】:

    • 可空相等性与选项#2 中的可空不等式有何不一致?
    • @MCS:这正是最初激发问题的方式。当
    • @Eric:谢谢 - 我认为“不等式”仅指 != 实际上与 == 一致。没想到这是一个数学术语:en.wikipedia.org/wiki/Inequality_(mathematics).
    • 好吧,另一个问题(您还没有解决)是当您尝试执行 <、<=、=> 或 > 时该怎么做操作数是null。在 C# 中,答案是返回 false。在 Scala/Java String 类中,答案是抛出一个NullPointerException。
    • @Brian:那为什么要允许可空类型的运算符呢?如果他们总是抛出可空类型的空值,那么您最好只在不可空类型上定义运算符,并让用户插入转换为不可空,因为这就是他们必须要做的事情做以消除异常。
    【解决方案3】:

    >= 仅在以特定明确定义的方式使用时表示“大于或等于”。当用于具有重载运算符的类时,它表示类开发人员希望它表示的任何含义。当应用于类似字符串的类时,它可能意味着“排序相同或更高”,也可能意味着“相同长度或更长”。

    【讨论】:

      【解决方案4】:

      另一种描述“>=”的方式是:不小于。没有提到平等。一旦不等式测试中的操作数之一为 Null,结果也是未知的(为 null)。但是,如果您想知道两个操作数是否为 Null,那么 Null == Null 是一个合理的测试(应该结果为真)。摆脱运算符的不等式部分会有所不同。

      http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4 中的以下代码示例总结了 C# 如何处理 Null:

      int? num1 = 10;   
      int? num2 = null;   
      if (num1 >= num2)   
      {   
          Console.WriteLine("num1 is greater than or equal to num2");   
      }   
      else   
      {   
          // This clause is selected, but num1 is not less than num2.   
          Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)");   
      }   
      
      if (num1 < num2)   
      {   
          Console.WriteLine("num1 is less than num2");   
      }   
      else   
      {   
          // The else clause is selected again, but num1 is not greater than   
          // or equal to num2.   
          Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)");   
      }   
      
      if (num1 != num2)   
      {   
          // This comparison is true, num1 and num2 are not equal.   
          Console.WriteLine("Finally, num1 != num2 returns true!");   
      }   
      
      // Change the value of num1, so that both num1 and num2 are null.   
      num1 = null;   
      if (num1 == num2)   
      {   
          // The equality comparison returns true when both operands are null.   
          Console.WriteLine("num1 == num2 returns true when the value of each is null");   
      }   
      
      /* Output:   
       * num1 >= num2 returned false (but num1 < num2 also is false)   
       * num1 < num2 returned false (but num1 >= num2 also is false)   
       * Finally, num1 != num2 returns true!   
       * num1 == num2 returns true when the value of each is null   
       */   
      

      【讨论】:

      • 这是一个有趣的心智模型。但是 C# 规范的第 1.4 节将这些运算符称为小于或等于和大于或等于
      • @Conrad 这只是说明了将编程语言(在本例中为 C#)翻译成英文的问题。恕我直言,每当 Null 进入逻辑时,您需要处理三态结果(真、假、未知)。任何涉及 Null 的表达式都应导致 unknown,但 Null == x 是一个例外,它是对 unknown 的显式测试,结果为真或假。
      • @NealB:实际上,规范声明 >= 和 = 意味着等于 或 大于/小于,正如人们所期望的那样。
      【解决方案5】:

      您期望什么值?

      null == null tr​​ue

      null >= null false

      null > null false

      null

      null

      null != null false

      1 == 空假

      1 >= 空假

      1> 空假

      1

      1

      1 != null tr​​ue aka !(1 == null)

      【讨论】:

        【解决方案6】:

        &gt;= 对数值进行运算;哪个 null 不是。

        您可以通过overload &gt;= 运算符在特定类型上提供您想要的内容。

        【讨论】:

        • 它确实对空类型进行操作,它返回 false
        • 它处理空类型是的......我们将定义为“操作”的语义。防御性编码;在评估期间做出决定时,它是否为 null 然后执行 x 与将 null 视为文字值。
        • 您通常不能重载运算符,因为您只能在它们自己的类中定义它们。因此,在这种情况下,您需要访问Nullable&lt;T&gt; 的代码。
        【解决方案7】:

        因为平等与可比性是分开定义的。
        您可以测试x == null,但x &gt; null 毫无意义。在 C# 中,它总是错误的。

        【讨论】:

        • +1:这是 MSDN 链接 msdn.microsoft.com/en-us/library/2cf62fcy.aspx,但不幸的是,他们忘记解释在 2 个空值情况下的比较运算符行为(他们只提到相等)...
        • 是的,但是运算符大于或相等。我看到了真值表,但我倾向于同意 OP,>= 更大 或 相等,如果 null==null 为真, null>=null 也应该为真。我想我们只是将其归结为实现和用户方便以保留 ==null 检查。
        • @David,请参阅 Eric 的回答,“这些选择显然都不正确”。但一般来说,当一个类型是 Equatable 但不是 Comparable 时,&gt;= 根本就没有定义。
        【解决方案8】:

        NULL 不是零(数字或二进制值)、零长度字符串或空白(字符值)。 因此,任何比较运算符都将始终返回 false 。 Read more about it here

        【讨论】:

        • 数据库 NULL 不是 C# null。此外,C# 可空类型上的比较运算符是一种奇怪的野兽,不一定遵循空比较的通常规则。
        • 答案还是对的,只是链接错了。 msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4
        • @unholy:答案是错误的,更重要的是,它基于错误的推理。
        猜你喜欢
        • 2021-07-02
        • 2016-11-14
        • 2016-03-29
        • 2013-09-18
        • 1970-01-01
        • 2015-06-22
        • 2015-06-21
        • 2021-11-10
        • 2017-07-29
        相关资源
        最近更新 更多