我正在实现一个可重用的DoubleEqualityComparer(具有自定义容差:“epsilon”构造函数参数),以便使用double序列来简化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)方法(不是很高效,我知道),但我请记住,当比较器与字典一起使用时,此解决方案会导致问题...
答案 0 :(得分:6)
我不确定使用EqualityComparer是否可行。因为比较的对象不等于。
也许您应该考虑使用简单的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));
}
答案 1 :(得分:1)
我会在NotSupportedException
中抛出GetHashCode
,这样你就可以吃蛋糕了。这为您提供了在LINQ和其他方法中使用IEqualityComparer
的便利,但保证GetHashCode
的任何使用都会爆炸。在实践中,您可能会发现使用相等比较器的方式实际上从不需要调用GetHashCode
。您甚至可以将此类NotHashableDoubleEqualityComparer
称为对调用者的限制非常清楚。