ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

C
Christian Gollhardt

当这个特性最初是在 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:那为什么要允许可空类型的运算符呢?如果他们总是抛出可空类型的空值,那么您不妨只在不可空类型上定义运算符并让用户插入转换为不可空,因为这就是他们必须要做的做以消除异常。
H
Henk Holterman

因为 Equality 与 Comparability 是分开定义的。
您可以测试 x == nullx > null 没有意义。在 C# 中,它总是错误的。


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

描述'>='的另一种方式是:不小于。没有提到平等。一旦不等式测试中的操作数之一为 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:实际上,规范指出 >= 和 <= 表示您期望它们的意思-第 7.10 节清楚地表明 <= 和 >= 的操作“x op y”是相等的-正如人们所期望的那样,等于或大于/小于。
A
Aaron McIver

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

您可以 overload >= 运算符来提供您想要的特定类型的内容。


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

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


数据库 NULL 不是 C# null。此外,C# 可空类型上的比较运算符是一种奇怪的野兽,不一定遵循空比较的通常规则。
答案还是对的,只是链接错了。 msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4
@unholy:答案是错误的,更重要的是,它基于错误的推理。
B
Bengie

您期望什么值?

空==空真

空 >= 空假

空>空假

空 <= 空假

空<空假

空!=空假

== 空假

>= 空假

> 空假

<= 空假

< 空假

!= null true aka !(1 == null)


S
Sparr

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


M
Mayer Spitz

由于默认情况下 int 不能为 null 并且其值将设置为 0,因此 > 的运算符和 <它是为 int 类型构建的,期望与 values 一起使用,而不是与 nulls 一起使用。

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