.NET Framework では、浮動小数点型 (および) のおよびの実装 ( override
)が間違っています。MSDN仕様から引用するには:Equals(object)
GetHashCode()
System.Double
System.Single
GetHashCode(object)
ハッシュ関数には、次のプロパティが必要です。
• 2 つのオブジェクトを比較して等しい場合、各オブジェクトの GetHashCode メソッドは同じ値を返す必要があります。ただし、2 つのオブジェクトが等しくない場合、2 つのオブジェクトの GetHashCode メソッドは異なる値を返す必要はありません。
バイナリ表現が異なる2 つのNaN
値を取得した場合、2 つのオブジェクトはメソッドの下で同等に比較されますEquals
が、ハッシュ コードは (ほとんどの場合) 異なります。
現在、このエラーはMicrosoft Connect で報告されています。しかし、なぜ彼らはこれを修正しないのでしょうか?
修正は簡単です: 異なるものを同等に比較しNaN
ないようにするか、任意の に対して返す固定ハッシュ コードを選択しますNaN
。
修正しても何も壊れません: 現在の状況では、異なるNaN
ものを使用すると何も機能しません。
これを修正しない理由を考えられますか?
現在の動作を示す簡単な例を次に示します。
using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
const int setSize = 1000000; // change to higher value if you want to waste even more memory
const double oneNaNToRuleThemAll = double.NaN;
static readonly Random randomNumberGenerator = new Random();
static void Main()
{
var set = new HashSet<double>(); // uses default EqualityComparer<double>
while (set.Count < setSize)
set.Add(GetSomeNaN());
Console.WriteLine("We now have a set with {0:N0} members", set.Count);
bool areAllEqualToTheSame = set.All(oneNaNToRuleThemAll.Equals);
if (areAllEqualToTheSame)
Console.WriteLine("By transitivity, all members of the set are (pairwise) equal.");
}
static double GetSomeNaN() // can also give PositiveInfinity, NegativeInfinity (unlikely)
{
byte[] b = new byte[8];
randomNumberGenerator.NextBytes(b);
b[7] |= 0x7F;
b[6] |= 0xF0;
return BitConverter.ToDouble(b, 0);
}
}
コードを実行した結果: HashSet<>
.
注意: これは、C#のand演算子とはまったく関係ありません。ご自身で確認したい場合にご利用ください。==
!=
Equals