2009-07-22 6 views
9

में GetHashCode विधि बनाना C# में कक्षा के लिए अपनी खुद की GetHashCode विधि बनाने का सबसे अच्छा तरीका क्या है? मान लीजिए मैं एक साधारण वर्ग (जो बराबर विधि ओवरराइड करता है) है, इस प्रकार है:सी #

class Test 
    { 
     public string[] names; 

     public double[] values; 

     public override bool Equals(object obj) 
     { 
     return (obj is Test) && this.Equals((Test)obj); 
     } 

     public bool Equals(Test t) 
     { 
     return names.Equals(t.names) && values.Equals(t.values); 
     } 
    } 

मैं GetHashCode विधि के लिए डिफ़ॉल्ट कोड उपयोग करना चाहिए?

public override int GetHashCode() 
    { 
    return base.GetHashCode(); 
    } 

क्या मुझे अपनी कक्षा की सामग्री पर विधि का आधार बनाना चाहिए?

public override int GetHashCode() 
    { 
    return names.GetHashCode() + values.GetHashCode() ; 
    } 

या मुझे कुछ और करना चाहिए?

+0

आप यहां ठीक से बराबर नहीं हैं। – jjnguy

+0

असल में, मुझे लगता है कि यह स्टैक ओवरफ्लो का कारण बन जाएगा। – jjnguy

+0

नहीं, यह ढेर बह जाएगा नहीं। हालांकि, यह काम नहीं करेगा, या तो। – SLaks

उत्तर

12

System.ArrayGetHashCode या Equals ओवरराइड नहीं करता है, इसलिए वे संदर्भ समानता का उपयोग करते हैं। इसलिए, आपको उन्हें कॉल नहीं करना चाहिए।

GetHashCode लागू करने के लिए, this question देखें।

Equals लागू करने के लिए, SequenceEqual एक्सटेंशन विधि का उपयोग करें।

संपादित: नेट 2.0 पर, आप SequenceEqual के अपने स्वयं के संस्करण लिखने के लिए इस तरह होगा:

public static bool SequenceEquals<T>(IList<T> first, IList<T> second) { 
    if (first == second) return true; 
    if (first == null || second == null) return false; 

    if (first.Count != second.Count) return false; 

    for (int i = 0; i < first.Count; i++) 
     if (!first[i].Equals(second[i])) 
      return false; 

    return true; 
} 

आप इसे लिख सकता है IList<T> के बजाय IEnumerable<T> लेने के लिए, लेकिन यह था कुछ हद तक धीमा हो क्योंकि पैरामीटर के अलग-अलग आकार होने पर यह जल्दी से बाहर निकलने में सक्षम नहीं होगा।

+0

धन्यवाद। क्या सीक्वेंस एक्वाल का कोई विकल्प है जो .NET Framework 2.0 के साथ काम करता है? –

2

यह सुनिश्चित करना वाकई महत्वपूर्ण है कि आप गेटहाशकोड() के ओवरराइड को चरण में Equals() के साथ रखें।

मूल रूप से

, आप सुनिश्चित करें कि वे एक ही क्षेत्रों पर विचार इतनी के रूप में (MSDN object.GetHashCode() से) GetHashCode के तीन नियमों का पहला उल्लंघन करने के लिए नहीं

दो वस्तुओं के रूप में बराबर की तुलना करना चाहिए, के लिए GetHashCode विधि प्रत्येक ऑब्जेक्ट को वही मान वापस करना होगा। हालांकि, यदि दो ऑब्जेक्ट्स के बराबर तुलना नहीं करते हैं, के लिए GetHashCode विधियों को दो ऑब्जेक्ट को अलग-अलग मानों को वापस करने की आवश्यकता नहीं है।

दूसरे शब्दों में, आपको यह सुनिश्चित करना होगा कि हर बार .क्वल्स दो उदाहरणों के बराबर मानते हैं, उनके पास भी वही होगा। GetHashCode()।

जैसा कि किसी और ने यहां बताया है, this question एक अच्छा कार्यान्वयन का विवरण देता है। यदि आप रुचि रखते हैं, तो मैंने पिछले साल की शुरुआत में हैश कोड की जांच करने पर कुछ ब्लॉग लेख लिखे थे। आप मेरे ramblings here (प्रथम ब्लॉग प्रविष्टि मैं विषय पर लिखा था)

1

वहाँ मुद्दों here का एक अच्छा चर्चा है पा सकते हैं, और सबसे हाल ही में अद्यतन BaseObject abstract class SharpArchitecture द्वारा प्रदान को दर्शाता है।

यदि आप कुछ और विज्ञापन चाहते हैं, तो मुझे पता चला है कि कोड जो ReSharper Equals() और GetHashCode() के लिए जेनरेट करता है ठीक है।