2009-09-14 8 views
7

MSDNIComparable और बराबर()

प्रकार है कि लागू IComparable Equals.Types कि ओवरराइड बराबर भी GetHashCode ओवरराइड चाहिए ओवरराइड चाहिए से; अन्यथा, हैशटेबल सही ढंग से काम नहीं कर सकता है।

मुझे यह काफी नहीं मिला। क्या कोई समझा सकता है।

+0

बराबर और GetHashCode के बीच संबंधों के लिए: http: // stackoverflow।कॉम/प्रश्न/371328/क्यों-यह-महत्वपूर्ण-से-ओवरराइड-गेटहाशकोड-कब-बराबर-विधि-है-ओवर्रिडेन-इन-सी –

+0

यह भी ध्यान रखें कि यह आवश्यक है कि आईसीओम्पेर्बल, बराबर, और GetHashCode() को हर मामले में पालन किया जाता है, इसलिए सभी तीनों को स्पष्ट रूप से लागू करने की आवश्यकता नहीं होती है, जब तक कि लगातार परिणाम प्राप्त किए जाते हैं। मुख्य रूप से इसका मतलब है कि एक ही हैश कोड वाले दो ऑब्जेक्ट बराबर हैं, और तुलनात्मक() पर 0 लौटाते हैं। – rushinge

+0

@ रुशिंग मुझे लगता है कि कथन गलत है: 'मुख्य रूप से इसका मतलब है कि एक ही हैश कोड वाले दो ऑब्जेक्ट बराबर हैं, और तुलनात्मक() पर 0 लौटाते हैं। । यदि ऑब्जेक्ट्स बराबर हैं तो यह अनुशंसा की जाती है कि GetHashCode() को वही मान वापस करने के लिए और तुलना करें() को वापस करने के लिए 0)। आप आसानी से अलग/समान बराबर उदाहरण उत्पन्न कर सकते हैं जो समान हैश कोड लौटाते हैं :) –

उत्तर

11

आईसीओम्पेर्बल एक इंटरफेस है जो परिभाषित करता है कि कार्यान्वयन वर्ग के दो उदाहरणों को एक दूसरे से कम या बराबर के रूप में देखा जा सकता है। चूंकि आपने उस इंटरफ़ेस के तरीकों में समानता को परिभाषित किया है, इसलिए आपको दोनों के परिणाम सुसंगत होने के लिए समानता विधि (और समानता ऑपरेटर) को ओवरराइड करने की आवश्यकता है।

public class EqualityTest : IComparable<EqualityTest> 
{ 
     public int Value { get; set; } 

     public int CompareTo(EqualityTest other) 
     { 
      return this.Value.CompareTo(other.Value); 
     } 
} 

ऊपर के उदाहरण मैं IComparable को लागू किया है में, लेकिन नहीं ओवरराइड बराबर होती है। यदि आप क्लास के दो अलग-अलग उदाहरणों के साथ तुलनात्मक को कॉल करते हैं, तो वही मान होगा जो कहेंगे कि बराबर हैं। यदि आप समान दो उदाहरणों के साथ समानता कहते हैं तो यह कहेंगे कि वे बराबर नहीं हैं क्योंकि यह जांचने के लिए परीक्षण करेगा कि वे एक ही वस्तु (समान के डिफ़ॉल्ट कार्यान्वयन) हैं या नहीं।

दो बराबर आइटम एक ही हैश कोड लौटना चाहिए (जल्दी से पाने के हैश तालिका में कुंजी के रूप में इस्तेमाल किया मदों के लिए उपयोग किया जाता है जो) ताकि आप को ओवरराइड करता है, तो फिर बराबर आप भी GetHashCode()


ओवरराइड करना चाहिए एक के रूप में उदाहरण मैं बस अपना आईडीई में निम्नलिखित श्रेणी का निर्माण:

public class EqualityTest 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
} 

और Resharper के सहायक "समानता उत्पन्न करें" समारोह कह रही है कि मैं समानता प्रभावित करने के लिए दोनों ए और बी चाहता था भाग गया।

public bool Equals(EqualityTest other) 
    { 
     if (ReferenceEquals(null, other)) 
     { 
      return false; 
     } 

     if (ReferenceEquals(this, other)) 
     { 
      return true; 
     } 

     return Equals(other.A, A) && Equals(other.B, B); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) 
     { 
      return false; 
     } 

     if (ReferenceEquals(this, obj)) 
     { 
      return true; 
     } 

     if (obj.GetType() != typeof(EqualityTest)) 
     { 
      return false; 
     } 

     return Equals((EqualityTest)obj); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      return ((A != null ? A.GetHashCode() : 0)*397)^(B != null ? B.GetHashCode() : 0); 
     } 
    } 

    public static bool operator ==(EqualityTest left, EqualityTest right) 
    { 
     return Equals(left, right); 
    } 

    public static bool operator !=(EqualityTest left, EqualityTest right) 
    { 
     return !Equals(left, right); 
    } 

तो अगर आप अधिभावी कर रहे हैं, इसके बराबर तो आप भी स्थिरता सुनिश्चित करने के लिए ऊपर के सभी परिभाषित करना चाहिए, यदि आप IComparable कार्यान्वित कर रहे हैं तो एक ही लागू होता है: इस कोड को यह बनाई गई है। Equals और GetHashCode

के लिए अपने ऑब्जेक्ट, सभी परिस्थितियों में ठीक से तुलना करने के लिए जब आप Equals विधि (कुछ तुलना के लिए प्रयोग किया जाता) को ओवरराइड, आपको:

+0

मेरे दिमाग में, यदि कोई मौजूद है संभावना है कि एक प्रकार आमतौर पर एक स्पष्ट रैंकिंग आदेश है, लेकिन मूल्यों के समूह मौजूद हो सकते हैं जो एक दूसरे के बराबर नहीं हैं, लेकिन जिनके पास एक-दूसरे के सापेक्ष कोई प्राकृतिक रैंकिंग नहीं है, यह 'तुलना करने के लिए' (''वापसी के लिए पूरी तरह से उचित होगा शून्य लेकिन 'बराबर()' के लिए झूठी वापसी के लिए (उदाहरण के लिए मैं मानता हूं कि 'दशमलव' '' 1.0m' और '1.00m' की तुलना करते समय उस तरीके से व्यवहार करना चाहिए)। मेरे दिमाग में, 'बराबर' को अपेक्षाकृत सख्त समानता संबंध परिभाषित करना चाहिए, यहां तक ​​कि उन मामलों में जहां '==' या 'तुलनात्मक' एक लूसर को परिभाषित कर सकता है। – supercat

0

इन दो तरीकों का अपने कोड में वस्तुओं की तुलना में किया जा सकता है GetHashCode (बाकी में भी उपयोग किया जाता है) को ओवरराइड करें।

यदि आप अपने कोड के आधार पर एक को ओवरराइड करते हैं, लेकिन दूसरे नहीं, तो आपको अप्रत्याशित परिणाम मिल सकते हैं।

1

IComparable दो वस्तुओं की तुलना के लिए प्रयोग किया जाता है - इन बराबर माना जाता है तो यह बहुत ही अप्रत्याशित अगर IComparable.Compare दो वस्तुओं के लिए शून्य लौट आए, अभी तक obj1.Equals (obj2) इस के बाद से झूठी लौटे होगा 0. वापस आ जाएगी की तुलना करें वस्तुओं के लिए समानता के दो अलग-अलग अर्थों का अर्थ है।

जब कोई वर्ग बराबर ओवरराइड करता है, तो उसे गेटहाशकोड को ओवरराइड करना चाहिए क्योंकि दो बराबर वस्तुओं को उसी मान पर हैश होना चाहिए, और यह हैश समानता के कार्यान्वयन में उपयोग किए जाने वाले फ़ील्ड/गुणों पर आधारित होना चाहिए।

+0

यदि IComparable.Compare शून्य देता है, क्या इसका वास्तव में मतलब है कि वस्तुओं को बराबर माना जाना चाहिए, या केवल इतना स्पष्ट आदेश नहीं है कि कोई स्पष्ट आदेश नहीं है? मान लें कि किसी के पास एक अपरिवर्तनीय कक्षा शेड्यूलेंट है जिसमें फ़ील्ड इवेंटटाइम टाइप डेटटाइम और इवेंट एक्शन प्रकार MethodInvoker शामिल है। EventEvent ऑब्जेक्ट्स इवेंटटाइम के आधार पर एक प्राकृतिक ऑर्डरिंग होगा, लेकिन मैं कभी भी उसी ईवेंटटाइम के साथ ऑब्जेक्ट शेड्यूलेंट ऑब्जेक्ट्स करता हूं लेकिन अलग-अलग प्रतिनिधियों को तुलनात्मक से 0 वापस करना चाहिए, लेकिन बराबर से गलत होना चाहिए। यह किसी भी अन्य व्यवहार से क्लीनर प्रतीत होता है। – supercat

संबंधित मुद्दे