这一切都始于有人向我提出的一个技巧问题。(书中提到 - 简而言之 C#)这是它的要点。
Double a = Double.NaN;
Console.WriteLine(a == a); // => false
Console.WriteLine(a.Equals(a)); // => true
上面的好像不太对。a 应该始终是 == 自身(引用相等)并且两者都应该是一致的。
似乎 Double 重载了 == 运算符。经反射器确认如下:
[__DynamicallyInvokable]
public static bool operator ==(double left, double right)
{
return (left == right);
}
奇怪的是看起来是递归的,没有提到 NaN 特定的行为。那么为什么它返回false呢?
所以我添加了一些代码来区分
var x = "abc";
var y = "xyz";
Console.WriteLine(x == y); // => false
现在我明白了
L_0001: ldc.r8 NaN
L_000a: stloc.0
L_000b: ldloc.0
L_000c: ldloc.0
L_000d: ceq
L_000f: call void [mscorlib]System.Console::WriteLine(bool)
L_0014: nop
L_0015: ldloca.s a
L_0017: ldloc.0
L_0018: call instance bool [mscorlib]System.Double::Equals(float64)
L_001d: call void [mscorlib]System.Console::WriteLine(bool)
L_0022: nop
L_0023: ldstr "abc"
L_0028: stloc.1
L_0029: ldstr "xyz"
L_002e: stloc.2
L_002f: ldloc.1
L_0030: ldloc.2
L_0031: call bool [mscorlib]System.String::op_Equality(string, string)
L_0036: call void [mscorlib]System.Console::WriteLine(bool)
- 对于双打, == 运算符调用转换为
ceq
IL 操作码 - 至于字符串,它转换为 System.String::op_Equality(string, string)。
果然,文档ceq
指定它是浮点数和 NaN 的特殊情况。这解释了观察结果。
问题:
- 为什么在 Double 上定义 op_Equality ?(并且实现不考虑 NaN 特定行为)
- 什么时候调用?