在 .NET Framework 中,浮点类型 (和) 的实现( override
)是错误的。引用MSDN规范:Equals(object)
GetHashCode()
System.Double
System.Single
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);
}
}
运行代码的结果:一百万个重复的HashSet<>
.
请注意:这与C#的and运算符完全无关。如果您想自己检查,请使用。==
!=
Equals