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

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

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

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

如果您使用不同的二进制表示forms获取两个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(); // uses default EqualityComparer 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#的==!=运算符没有任何关系 。 如果您想亲自检查,请使用Equals