2012-06-29 20 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) 
     { 
      // ? 
     } 
    } 

पुनश्च:: मैं हमेशा समान मान कर सकते हैं:; हमेशा बराबर करने के लिए कॉल (डबल, डबल) विधि मजबूर करने के लिए (नहीं बहुत (पूर्व GetHashCode (डबल obj) {0 लौट}) कोड यह कलाकार, मुझे पता है), लेकिन मुझे याद है कि इस समाधान में समस्याएं होती हैं जब तुलनाकर्ता को शब्दकोश के साथ प्रयोग किया जाता है ...

+8

आपको ऐसा नहीं करना चाहिए क्योंकि यह पारगमनशीलता का उल्लंघन करता है। यह संभव है कि 'बराबर बी' और 'बी बराबर सी 'लेकिन' सी बराबर नहीं है'। – Ani

उत्तर

4

मुझे यकीन नहीं है कि इक्वालिटी कॉम्पैयर का उपयोग करने का तरीका है। क्योंकि तुलना की गई वस्तुओं बराबर नहीं हैं।

शायद तुम एक साधारण 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

धन्यवाद, आप और Ani मुझे IEqualityComparer उपयोग करने के लिए नहीं है, लेकिन एक कस्टम इंटरफ़ेस (और विस्तार के तरीकों, LINQ शैली की अपनी सेट) को परिभाषित करने के लिए राजी कर लिया: सार्वजनिक इंटरफ़ेस ITolerable { bool AreAlmostEqual (टी एक्स, टी वाई) ; } IEqualityComparer आसान था क्योंकि LINQ आधिकारिक विधियों का उपयोग करने के लिए तैयार हैं (जो GetHashcode को कॉल नहीं करते हैं), लेकिन मैं इसे छोड़ने के लिए अवांछित नहीं था (और खतरनाक)। – Notoriousxl

1

मैं GetHashCode में NotSupportedException फेंक ताकि आप अपने केक है और यह भी खा सकते हैं। यह आपको LINQ और अन्य विधियों में IEqualityComparer रखने की सुविधा देता है, लेकिन गारंटी देता है कि GetHashCode का कोई भी उपयोग उड़ाता है। व्यावहारिक रूप से, आप पाते हैं कि जिस तरह से आप समानता तुलनाकर्ता का उपयोग करते हैं, उसे वास्तव में कभी भी GetHashCode कॉल करने की आवश्यकता नहीं होती है। कॉलर्स की सीमा के बारे में सुपर स्पष्ट होने के लिए आप इस कक्षा NotHashableDoubleEqualityComparer को भी कॉल कर सकते हैं।