16

.NET Framework では、浮動小数点型 (および) のおよびの実装 ( override)が間違っています。MSDN仕様から引用するには:Equals(object)GetHashCode()System.DoubleSystem.SingleGetHashCode(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

4

0 に答える 0