可为null<;=vs==比较结果
本文关键字:vs 结果 比较 null lt 可为 | 更新日期: 2023-09-27 18:05:44
我觉得这种行为不对。
DateTime? birth = null;
DateTime? death = null;
Console.WriteLine(birth == death); // true
Console.WriteLine(birth <= death); // false
为什么会这样?这太奇怪了。当然,我的意思是为什么第二个表达式也不能计算为true
。
编辑:
我知道以下比较返回false
,因为无法说明它们之间的关系:
Console.WriteLine(birth < death); // false
Console.WriteLine(birth > death); // false
这是完全可以理解的行为。但是看看逻辑:
<=
表示<
或==
- 我们不知道如何读取
<
——它可能是true
或false
- 我们知道
==
就是true
- 由于其中一个条件是
true
,所以另一个条件不能不真实结果。这是逻辑或,而不是和
我的观点是true or something else
应该为真。
我知道C#团队是这样设计的,但我的直觉不同。既然聪明人已经用这样的规则编写了C#,我只想了解为什么我的直觉在这里是错误的:(
根据ECMA-334标准(8.19可为空类型((emphasis mine(:
当操作数类型都是不可为null的值类型并且结果类型为时,比较运算符(
==
、!=
、<
、>
、<=
、>=
(具有提升形式bool
。比较运算符的提升形式是通过添加?
修饰符用于每个操作数类型(但不用于结果类型(。==
的提升形式和!=
运算符认为两个null值相等,一个null值不等于一个非null值。<
、>
、<=
和>=
的提升形式如果一个或两个操作数都为null,则运算符返回false。
我理解你不是在寻找规范,而是在解释为什么可以用这种方式设计null。
为了消除歧义,设计者可以让这些运算符返回bool?
值,而不是在其中一个操作数为空的情况下为空的bool
值。
但如果他们做出了这个选择,代码看起来会是:
bool? comparison = birth <= death;
if (comparison.HasValue && comparison.Value)
{
}
这有点麻烦。
顺便说一句,看起来,在IL中,C#编译器首先生成与默认值的比较,然后检查其中一个操作数是否为空,这似乎有点奇怪。。。
.method private hidebysig static void Main(string[] args) cil managed
{
.locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> x,
[1] valuetype [mscorlib]System.Nullable`1<int32> V_1,
[2] valuetype [mscorlib]System.Nullable`1<int32> V_2)
IL_0000: ldloca.s x
IL_0002: ldc.i4.1
IL_0003: call instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
IL_0008: ldc.i4.2
IL_0009: newobj instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
IL_000e: ldloc.0
IL_000f: stloc.1
IL_0010: stloc.2
IL_0011: ldloca.s V_1
IL_0013: call instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
IL_0018: ldloca.s V_2
IL_001a: call instance !0 valuetype [mscorlib]System.Nullable`1<int32>::GetValueOrDefault()
IL_001f: ble.s IL_0024
IL_0021: ldc.i4.0
IL_0022: br.s IL_0033
IL_0024: ldloca.s V_1
IL_0026: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_002b: ldloca.s V_2
IL_002d: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
IL_0032: and
IL_0033: brfalse.s IL_003a
IL_0035: call void [mscorlib]System.Console::WriteLine()
IL_003a: ret
} // end of method Program::Main
它还复制了静态Nullable类中已经存在的逻辑。