【发布时间】:2012-06-30 19:38:34
【问题描述】:
我正在实现一个可重用的 DoubleEqualityComparer(具有自定义容差:“epsilon”构造函数参数),以简化 LINQ 与 double 序列的使用。例如:
bool myDoubleFound = doubles.Contains(myDouble, new DoubleEqualityComparer(epsilon: 0.01));
什么是实现GetHashCode的正确方法?代码如下:
public class DoubleEqualityComparer : IEqualityComparer<double>, IEqualityComparer<double?>
{
private readonly double epsilon;
public DoubleEqualityComparer(double epsilon)
{
if (epsilon < 0)
{
throw new ArgumentException("epsilon can't be negative", "epsilon");
}
this.epsilon = epsilon;
}
public bool Equals(double x, double y)
{
return System.Math.Abs(x - y) < this.epsilon;
}
public int GetHashCode(double obj)
{
// ?
}
}
PS:我总是可以返回相同的值(例如:GetHashCode(double obj){ return 0; })以始终强制调用 Equals(double, double) 方法(我知道,性能不是很好),但我请记住,当比较器与字典一起使用时,此解决方案会导致问题...
【问题讨论】:
-
你不应该这样做,因为它违反了传递性。
a equals b和b equals c可能是a not equals c。 -
我有一个类似的问题,关于几何中的点,出于所有意图和目的,如果它们“足够接近”,则认为它们是相等的,因为双精度的存储方式和公差是必需的,所以如果相等您的哈希码应该生成一个相同的哈希,因此当尝试使用字典来跟踪和存储相同的点时,它会由于错误的 GetHashCode 方法而分崩离析。字典有用的原因有很多
标签: .net double hashcode iequalitycomparer epsilon