2009-07-02 17 views
5

असल में, मैं अब तक निम्नलिखित है:जटिल समानता के लिए ऑब्जेक्ट.गेटहाशकोड() को कार्यान्वित करने के बारे में मुझे कैसे जाना चाहिए?

class Foo { 
    public override bool Equals(object obj) 
    { 
     Foo d = obj as Foo ; 
     if (d == null) 
      return false; 

     return this.Equals(d); 
    } 

    #region IEquatable<Foo> Members 

    public bool Equals(Foo other) 
    { 
     if (this.Guid != String.Empty && this.Guid == other.Guid) 
      return true; 
     else if (this.Guid != String.Empty || other.Guid != String.Empty) 
      return false; 

     if (this.Title == other.Title && 
      this.PublishDate == other.PublishDate && 
      this.Description == other.Description) 
      return true; 

     return false; 
    } 
} 

तो, समस्या यह है: मैं एक गैर आवश्यक फ़ील्ड Guid है, जो एक अद्वितीय पहचानकर्ता है। यदि यह सेट नहीं है, तो मुझे यह निर्धारित करने के प्रयास के रूप में कम सटीक मीट्रिक के आधार पर समानता निर्धारित करने की आवश्यकता है कि दो ऑब्जेक्ट बराबर हैं या नहीं। यह ठीक काम करता है, लेकिन यह GetHashCode() गन्दा बनाता है ... मुझे इसके बारे में कैसे जाना चाहिए? एक अनुभवहीन कार्यान्वयन कुछ की तरह होगा:

public override int GetHashCode() { 
    if (this.Guid != String.Empty) 
     return this.Guid.GetHashCode(); 

    int hash = 37; 
    hash = hash * 23 + this.Title.GetHashCode(); 
    hash = hash * 23 + this.PublishDate.GetHashCode(); 
    hash = hash * 23 + this.Description.GetHashCode(); 
    return hash; 
} 

लेकिन हैश टकराने के दो प्रकार की संभावना क्या हैं? निश्चित रूप से, मैं उम्मीद नहीं करता कि यह 1 in 2 ** 32 हो। क्या यह एक बुरा विचार है, और यदि हां, तो मुझे यह कैसे करना चाहिए?

+0

यह अधिक महत्वपूर्ण है कि आपके हैश एल्गोरिदम वितरण की तुलना में आपके समानता एल्गोरिदम से सहमत हैं। याद रखें, हैश का उद्देश्य पूरी तरह से हैश तालिका में सभ्य वितरण प्राप्त करना है; जब तक आप एक विशेष बाल्टी के लिए बड़े पैमाने पर skewed नहीं हैं, बाधाएं अच्छी हैं आप ठीक हो जाएगा। यदि आप चिंतित हैं, तो एक उचित परिदृश्य चुनें कि आपके ऑब्जेक्ट के उपभोक्ता को सामना करना पड़ सकता है - कहें, उनमें से कुछ सौ एक शब्दकोश में डालें, यदि यह उचित है - और यह देखने के लिए कुछ पेर्फ परीक्षण करें कि आप स्वीकार्य हैं या नहीं परिणाम है। –

+0

मैंने कभी भी वास्तविक उपयोग में देखा है ~ 200 था, लेकिन सामान्य उपयोग <30 है, तो आप शायद सही हैं। –

+1

हेक, 30 से कम वस्तुओं के साथ, एक लिंक्ड सूची में एक रैखिक खोज संभवतः निष्पादक है। आप हमेशा शून्य का हैश कोड वापस कर सकते हैं, टकराव का 100% मौका है, और फिर भी स्वीकार्य प्रदर्शन मिलता है। हैश कोड का अच्छा वितरण होने का बिंदु प्रदर्शन आकार को बड़ा करना है जब शब्दकोश का आकार बड़ा हो जाता है। यदि आप केवल टेबल में छोटी संख्या में आइटम डालने जा रहे हैं तो आप एक लुभावनी वितरण कर सकते हैं और अभी भी अच्छे परिणाम प्राप्त कर सकते हैं। –

उत्तर

4

मुझे नहीं लगता कि आपके द्वारा उपयोग किए जाने वाले दृष्टिकोण के साथ कोई समस्या है। हैश टकराव के बारे में 'बहुत ज्यादा' चिंता करना हमेशा समस्या को खत्म करने का संकेत है; जब तक हैश अत्यधिक अलग होने की संभावना है, तब तक आपको ठीक होना चाहिए।

आखिरकार आप अपने हैश से Description को छोड़ने पर भी विचार करना चाहेंगे, अगर यह अपेक्षा करना उचित है कि अधिकांश समय वस्तुओं को उनके शीर्षक और प्रकाशन तिथि (किताबें?) के आधार पर अलग किया जा सकता है।

तुम भी पूरी तरह अपने हैश समारोह में GUID अनदेखी विचार कर सकते हैं, और केवल Equals कार्यान्वयन में इसका इस्तेमाल संभावना नहीं (?) हैश संघर्ष के मामले को स्पष्ट करने के लिए।

+0

जाहिर है, यदि मौजूद है तो GUID, मनमानी शीर्षक स्ट्रिंग से बहुत तेज़ है ... इसलिए यह एक व्यवहार्य प्रदर्शन अनुकूलन हो सकता है। – jerryjvl

+0

विवरण समानता (और इसलिए हैश कोड में) –

+0

ओह, और रिकॉर्ड के लिए, आरएसएस आइटम में शामिल करने की आवश्यकता है। –

7

एक बहुत ही आसान hash code method for custom classes एक फ़ील्ड हैश कोडों में से प्रत्येक को थोड़ा सा है। यह इस रूप में सरल किया जा सकता है:

int hash = 0; 
hash ^= this.Title.GetHashCode(); 
hash ^= this.PublishDate.GetHashCode(); 
hash ^= this.Description.GetHashCode(); 
return hash; 

link above से:

XOR निम्नलिखित अच्छा गुण है:

  • यह गणना के आदेश पर निर्भर नहीं करता है।
  • यह बिट्स को "बर्बाद" नहीं करता है। यदि आप घटकों में से एक में भी एक बिट बदलते हैं, तो अंतिम मान बदल जाएगा।
  • यह त्वरित है, यहां तक ​​कि सबसे प्राचीन कंप्यूटर पर एक चक्र भी है।
  • यह समान वितरण को संरक्षित करता है। यदि आपके द्वारा एकत्र किए गए दो टुकड़े समान रूप से वितरित होते हैं तो संयोजन होगा। दूसरे शब्दों में, यह पाचन की सीमा को एक संकुचित बैंड में पतन नहीं करता है।

XOR अच्छी तरह से काम नहीं करता है अगर आप अपने क्षेत्र में डुप्लिकेट मानों के लिए के रूप में डुप्लिकेट मानों जब XORed बाहर एक दूसरे को रद्द कर देंगे उम्मीद है। चूंकि आप तीन असंबद्ध क्षेत्रों को एक साथ जोड़ रहे हैं जो इस मामले में कोई समस्या नहीं होनी चाहिए।

+7

एक्सओआर गणना के क्रम के आधार पर नहीं है एक दो तलवार वाली तलवार है ... यदि आपके पास एक ही प्रकार के कई क्षेत्रों (उदाहरण के लिए, दो तिथियां) के साथ ऑब्जेक्ट्स हैं, तो जब ये ऑब्जेक्ट्स के चारों ओर बदल जाते हैं तो वे समान दिखेंगे 'हैश के लिए। – jerryjvl