我有两个 int? 类型的变量(或者如果你愿意,可以理解为 Nullable<int>)。我希望对这两个变量进行大于等于(>=)的比较,但是事实证明,如果两个变量都是 null,这将返回 false,而显然 == 运算符会返回 true。
有人能够解释一下这种情况为什么是合理的吗?因为“大于等于”运算符的语义定义中包含了单词“或”。
我有两个 int? 类型的变量(或者如果你愿意,可以理解为 Nullable<int>)。我希望对这两个变量进行大于等于(>=)的比较,但是事实证明,如果两个变量都是 null,这将返回 false,而显然 == 运算符会返回 true。
有人能够解释一下这种情况为什么是合理的吗?因为“大于等于”运算符的语义定义中包含了单词“或”。
当C# 2.0最初设计这个奇怪的特性时,引起了一场巨大的争论。问题在于C#用户完全习惯了它具有意义:
if(someReference == null)
当将等式扩展到可空值类型时,您有以下选择:
可空相等性是真正的“提升”。如果操作数中的一个或两个为 null,则结果既不为 true 也不为 false,而是 null。在这种情况下,您可以:
a) 在 if 语句中禁止使用可空值类型等式,因为 if 语句需要 bool 而不是可空 bool。相反,要比较 null,请要求每个人都使用 HasValue。这很啰嗦和烦人。
b) 自动将 null 转换为 false。这样做的缺点是,如果 x 为 null,则 x==null 返回 false,这会与人们对引用类型的 null 比较所理解的相反。
可空相等性未被提升。可空相等性要么为 true,要么为 false,并且与 null 进行比较是一种 null 检查。这使得可空相等性与可空不等式不一致。
这些选择都没有明显的正确答案;它们都有利弊。例如,VBScript 选择了 1b。经过长时间的讨论,C# 设计团队选择了 #2。
<
,<=
,=>
或>
该怎么办。在C#中,答案是返回“false”。在Scala / Java的“String”类中,答案是抛出“NullPointerException”。 - Ken Bloomif(someReference == null)
,但实际上不应该这样做。这可能是一个方便的权宜之计,但会导致像这样的问题,从而产生内部矛盾的无意义答案。这似乎与成功之坑的本质相反。 - nicodemus13因为相等性和可比性是分别定义的。
您可以测试 x == null
但 x > null
毫无意义。在 C# 中它总是为false。
>=
根本没有定义。 - H H'>='的另一种表述方式是:不小于。没有提到相等。在非相等测试中,只要有一个操作数为Null,则结果也为未知(即为Null)。但是,如果你想知道两个操作数是否都为Null,则Null == Null是一个合理的测试(应该返回true)。去掉不等的部分就会产生很大的区别。
下面的代码示例来自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
*/
Null == x
,它是一个明确测试未知结果为真或为假的条件。 - NealB>=
操作符用于数值,而 null 不是数值。
您可以 重载 >=
操作符以实现特定类型的需求。
Nullable<T>
的代码。 - ANeves由于默认情况下,int
不能为 null,其值将被设置为 0
,而为 int
类型构建的 > 和 < 运算符期望使用 values
而不是 nulls
。
请参阅我对类似问题的答案,在那里我写了一些处理带有 less <
和 greater >
运算符的可空 int
的方法 https://dev59.com/wGkv5IYBdhLWcg3w_Vqn#51507612
你会期望什么值?
null == null true
null >= null false
null > null false
null <= null false
null < null false
null != null false
1 == null false
1 >= null false
1 > null false
1 <= null false
1 < null false
1 != null true aka !(1 == null)
>= 只有在特定的明确定义方式下使用时才表示“大于或等于”。当用于具有重载运算符的类时,它可以表示类开发人员想要的任何含义。当应用于类似字符串的类时,它可能表示“排序相同或更高”或者可能表示“相同长度或更长”。
NULL不是零(数字或二进制值),也不是零长度的字符串或空白(字符值)。 因此,任何比较运算符在其上始终返回false。 在这里阅读更多相关信息
null
。此外,在 C# 可空类型上进行比较运算符是一种奇怪的行为,它并不一定遵循通常用于空值比较的规则。 - Joren
int?
),那么它们的值是已知的。null
。 - Moo-JuiceNull
),但是这个变量代表的真正问题领域实体/值是未知的。 - Charles Bretana