为啥当 == 为空值返回 true 时 >= 返回 false?

Posted

技术标签:

【中文标题】为啥当 == 为空值返回 true 时 >= 返回 false?【英文标题】: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,喜欢这个比喻!。但是谁没有打破玻璃? 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

if(someReference == null)

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

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

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

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

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

这些选择显然都不正确;他们都有优点和缺点。例如,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:答案是错误的,更重要的是,它基于错误的推理。

以上是关于为啥当 == 为空值返回 true 时 >= 返回 false?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Stream.allMatch() 为空流返回 true?

空值的传递后判断为空的问题.

为啥 Array.prototype.every 在空数组上返回 true?

mybatis insert 插入为啥会返回空值

在sql中我设置列表的类型时没有设置为空,还有主键都设置了,为啥在ASP中输入的数据还是可以插入空值的

为啥 all() 为空的可迭代对象返回 True? [复制]