这一切都始于一个有趣的问题,有人向我提出.(它在书中提到 - 简而言之C#)下面是它的要点.
Double a = Double.NaN;
Console.WriteLine(a == a); // => false
Console.WriteLine(a.Equals(a)); // => true
Run Code Online (Sandbox Code Playgroud)
以上似乎不对.a应始终为==自身(引用相等)并且两者应该是一致的.
看起来像Double重载==运算符.反射器确认如下:
[__DynamicallyInvokable]
public static bool operator ==(double left, double right)
{
return (left == right);
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是看起来递归并且没有提到NaN特定的行为.那为什么它会返回假?
所以我添加了一些代码来区分
var x = "abc";
var y = "xyz";
Console.WriteLine(x == y); // => false
Run Code Online (Sandbox Code Playgroud)
现在我明白了
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 …Run Code Online (Sandbox Code Playgroud) 我正在审查一些原始类型的实现,特别是System.Double在.NET的Reference Source中,我偶然发现了这个:
[System.Runtime.Versioning.NonVersionable]
public static bool operator ==(Double left, Double right) {
return left == right;
}
[System.Runtime.Versioning.NonVersionable]
public static bool operator !=(Double left, Double right) {
return left != right;
}
Run Code Online (Sandbox Code Playgroud)
我知道这种自我参照运营商的实现可以反编译问题,因为解释在这里,但我的印象是,在参考源中的代码是实际的源代码和反编译的不输出下.
谁能解释一下这里真的发生了什么?