11

我正在实现一个可重用的 DoubleEqualityComparer(具有自定义容差:“epsilon”构造函数参数),以简化 LINQ 与双序列的使用。例如:

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) 方法(我知道不是很高效),但我记得这个当比较器与字典一起使用时,解决方案会导致问题......

4

2 回答 2

6

我不确定使用IEqualityComparer<T>是要走的路。因为比较的对象不相等。

也许你应该考虑使用一个简单的Any子句+一个实用方法:

private static bool DoublesAreNearlyEquals(double d1, double d2, double epsilon = 0.01D)
{
    return System.Math.Abs(d1 - d2) < this.epsilon;
}

private void foo()
{
    var myDoubles = Getdoubles();
    var doubleToSearch = 42D;
    var result = myDoubles.Any(d=>DoublesAreNearlyEquals(d, doubleToSearch));
}
于 2012-06-29T09:26:02.493 回答
2

我会投NotSupportedException进去,GetHashCode这样你就可以吃蛋糕了。这为您提供了使用IEqualityComparerin LINQ 和其他方法的便利,但保证了任何使用都会GetHashCode崩溃。在实践中,您可能会发现使用相等比较器的方式实际上不需要GetHashCode调用。你甚至可以调用这个类NotHashableDoubleEqualityComparer来非常清楚对调用者的限制。

于 2016-06-03T15:49:20.970 回答