それはすべて、誰かが私に提起したひっかけ問題から始まりました.. (本で言及されています - 一言で言えば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)
- double の場合、== 演算子呼び出しは
ceq
IL オペコードに変換されます - 文字列については、System.String::op_Equality(string, string) に変換されます。
確かに、のドキュメントでceq
は、浮動小数点数と NaN の特殊なケースであると指定されています。これは観察を説明します。
質問:
- op_Equality が Double で定義されているのはなぜですか? (そして、実装は NaN 固有の動作を考慮していません)
- いつ呼び出されますか?