Dot-Net

帶有容差的 IEqualityComparer<double>;如何實現GetHashCode?

  • September 24, 2021

我正在實現一個可重用的 DoubleEqualityComparer(具有自定義容差:“epsilon”建構子參數)以簡化 LINQ 與雙序列的使用。例如:

bool myDoubleFound = doubles.Contains(myDouble, new DoubleEqualityComparer(epsilon: 0.01));

實現 GetHashCode 的正確方法是什麼?這是程式碼:

  public class DoubleEqualityComparer : IEqualityComparer&lt;double&gt;, IEqualityComparer&lt;double?&gt;
   {
       private readonly double epsilon;

       public DoubleEqualityComparer(double epsilon)
       {
           if (epsilon &lt; 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) &lt; this.epsilon;
       }

       public int GetHashCode(double obj)
       {
           // ?
       }
  }

PS:我總是可以返回相同的值(例如:GetHashCode(double obj){ return 0; }) 總是強制呼叫 Equals(double, double) 方法(我知道不是很高效),但我記得這個當比較器與字典一起使用時,解決方案會導致問題……

我不確定使用IEqualityComparer&lt;T&gt;是要走的路。因為比較的對像不相等。

也許你應該考慮使用一個簡單的Any子句+一個實用方法:

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

private void foo()
{
   var myDoubles = Getdoubles();
   var doubleToSearch = 42D;
   var result = myDoubles.Any(d=&gt;DoublesAreNearlyEquals(d, doubleToSearch));
}

我會投NotSupportedException進去,GetHashCode這樣你就可以吃蛋糕了。這為您提供了使用IEqualityComparerin LINQ 和其他方法的便利,但保證了任何使用都會GetHashCode崩潰。在實踐中,您可能會發現使用相等比較器的方式實際上不需要GetHashCode呼叫。你甚至可以呼叫這個類NotHashableDoubleEqualityComparer來非常清楚對呼叫者的限制。

引用自:https://stackoverflow.com/questions/11258962