为什么微软希望不用NaN修复错误的Equals和GetHashCode实现?

Jep*_*sen 16 .net c# floating-point hash nan

在.NET Framework中,实现(override中)Equals(object)GetHashCode()浮点型(System.DoubleSystem.Single)是错误的.引用MSDN GetHashCode(object)规范:

哈希函数必须具有以下属性:

•如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值.但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值.

如果NaN使用具有不同二进制表示的两个值,则这两个对象在该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);
  }
}
Run Code Online (Sandbox Code Playgroud)

运行代码的结果:一百万个重复HashSet<>.

请注意:这有什么都做的==!=C#的运营商.Equals如果您想亲自检查,请使用.