2012-06-29 7 views
5

이중 순서로 LINQ를 쉽게 사용할 수 있도록 재사용 가능한 DoubleEqualityComparer (사용자 지정 허용 오차 : "엡실론"생성자 매개 변수 사용)을 구현하고 있습니다. 예 :IEqualityComparer <double> 허용 오차가 있습니다. GetHashCode를 구현하는 방법?

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는 (더블 obj가) {0 반환}) 여기 코드는 performant, 나도 알아),하지만이 솔루션은 비교자를 사전에 사용할 때 문제가 발생한다는 것을 기억합니다 ...

+8

과도 성을 위반하기 때문에이 작업을 수행하지 마십시오. 'a는 b와 같고 b는 c와 같지만'a는 c와 같지 않을 수도 있습니다. – Ani

답변

4

나는 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

덕분에, 당신과 애니 날 IEqualityComparer를 사용하지만, 사용자 인터페이스 (및 확장 방법, LINQ 스타일의 그것의 세트)를 정의하지 않는 확신 : 공용 인터페이스 ITolerable { 부울 AreAlmostEqual (T의 X, T y를) ; } 사용할 수있는 LINQ 공식 메서드 (GetHashcode를 호출하지 않음)가 있기 때문에 IEqualityComparer가 유용했으나 구현되지 않은 상태로 남겨 두지 않았습니까 (위험한 경우). – Notoriousxl

1

나는 그래서 당신은 당신의 케이크를 가질 수 너무 먹을 GetHashCodeNotSupportedException를 던질 것입니다. 이렇게하면 LINQ 및 기타 방법에서 IEqualityComparer을 사용할 수있는 편리함을 얻을 수 있지만 GetHashCode의 사용량은 모두 폭발적입니다. 실제적으로 동등 비교자를 사용하는 방법은 실제로는 GetHashCode이 호출되지 않아도된다는 것을 알 수 있습니다. 이 클래스 NotHashableDoubleEqualityComparer을 호출자의 제한 사항에 대해 매우 명확하게 지정할 수도 있습니다.