2012-06-29 37 views
5

(özel bir toleransla "epsilon" yapıcı parametresi) çift dizileri ile LINQ kullanımını kolaylaştırmak için. Örneğin:IEqualityComparer toleransla <double>; GetHashCode nasıl uygulanır? Bir yeniden kullanılabilir DoubleEqualityComparer uygulanması ediyorum

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

GetHashCode'u uygulamanın doğru yolu nedir?

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: Hep aynı değeri döndürebilir:; hep Eşittir çağrısı (çift, çift) yöntemi zorlamak için (değil çok (ex GetHashCode (çift obj) {0 return}) İşte kod performant,

+8

Bunu yapmamalıyız. 'A eşittir b' ve 'b eşittir c' ancak 'eşit değil c'. – Ani

cevap

4

ben EqualityComparer kullanarak gitmek yoludur emin değilim ... Ben) biliyorum ama karşılaştırıcısı bir sözlükle kullanıldığında bu çözüm sorunlarına neden olduğunu unutmayın. Çünkü karşılaştırılan nesneler eşit değildir.

Belki basit Any maddesini + an yarar yöntemini kullanmayı düşünmelisiniz:

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

sayesinde, ve Ani beni IEqualityComparer kullanmak, ancak özel bir arayüz (ve uzatma yöntemleri LINQ tarzı onun kümesi) tanımlamak için değil ikna: kamu arayüzü ITolerable { bool AreAlmostEqual (T x T y) ; korkunç (ve tehlikeli) orada edildi (GetHashCode demiyoruz) kullanıma hazır LINQ resmi yöntemlerdir, ama uygulanmadı bırakmak undestand çünkü } IEqualityComparer kullanışlı oldu. – Notoriousxl

1

Ben böylece kek olabilir ve çok yemek GetHashCode yılında NotSupportedException atardı. Bu, LINQ ve diğer yöntemlerde bir IEqualityComparer sahip kolaylık verir, ama GetHashCode herhangi kullanım patlarsa güvence altına alır. Pratikte, eşitlik karşılaştırıcısını kullanma şeklinizin aslında hiçbir zaman GetHashCode'un çağrılmasını gerektirdiğini görebilirsiniz. Arayanların sınırlandırılması konusunda süper net olmak için NotHashableDoubleEqualityComparer numaralı sınıfı bile arayabilirsiniz. o geçişlilik ihlal ettiğinden