为啥当 == 为空值返回 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
有人可以向我解释为什么这是合乎逻辑的,因为 >= 运算符的语义定义包含单词“或”吗?
【问题讨论】:
你能发布产生这种奇怪行为的代码吗? 实际上,我会质疑 == 返回 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 true
null >= null false
null > null false
null
null null != null false 1 == 空假 1 >= 空假 1> 空假 1
1
1 != null true aka !(1 == null)
【讨论】:
【参考方案6】:>=
对数值进行运算;哪个 null 不是。
您可以通过overload >=
运算符在特定类型上提供您想要的内容。
【讨论】:
它确实对空类型进行操作,它返回 false 它处理空类型是的......我们将定义为“操作”的语义。防御性编码;在评估期间做出决定时,它是否为 null 然后执行 x 与将 null 视为文字值。 您通常不能重载运算符,因为您只能在它们自己的类中定义它们。因此,在这种情况下,您需要访问Nullable<T>
的代码。【参考方案7】:
因为平等与可比性是分开定义的。
您可以测试x == null
,但x > null
毫无意义。在 C# 中,它总是错误的。
【讨论】:
+1:这是 MSDN 链接 msdn.microsoft.com/en-us/library/2cf62fcy.aspx,但不幸的是,他们忘记解释在 2 个空值情况下的比较运算符行为(他们只提到相等)... 是的,但是运算符大于或相等。我看到了真值表,但我倾向于同意 OP,>= 更大 或 相等,如果 null==null 为真, null>=null 也应该为真。我想我们只是将其归结为实现和用户方便以保留 ==null 检查。 @David,请参阅 Eric 的回答,“这些选择显然都不正确”。但一般来说,当一个类型是 Equatable 但不是 Comparable 时,>=
根本就没有定义。【参考方案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?