2009-09-10 11 views
12

मैंने कई उद्देश्यों के लिए शब्दकोश (टीके, टीवीएयू) का उपयोग किया है। लेकिन मुझे GetHashCode() को लागू करने के लिए किसी भी परिदृश्य का सामना नहीं हुआ है, जो मुझे विश्वास है क्योंकि मेरी चाबियाँ प्राथमिक प्रकार की थीं जैसे int और स्ट्रिंग। मैं परिदृश्यों (असली दुनिया उदाहरण) पता करने के लिए जब एक कुंजी के लिए एक कस्टम वस्तु का उपयोग करना चाहिए और इस तरह के तरीकों GetHashCode लागू (उत्सुक) कर रहा हूँ, इसके बराबर() आदिहम एक शब्दकोश के लिए GetHashCode() कब करते हैं?

और, कुंजी की जरूरत इन लागू करने के लिए एक कस्टम वस्तु का उपयोग करता है कार्यों?

+0

संभावित डुप्लिकेट [बराबर विधि ओवरराइड होने पर GetHashCode को ओवरराइड करना क्यों महत्वपूर्ण है?] (Http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when- बराबर-विधि-ओवर-ऑर्डर) – nawfal

उत्तर

13

आपको Equals और GetHashCode ओवरराइड करना चाहिए जब भी डिफ़ॉल्ट Object.Equals (संदर्भ समानता के लिए परीक्षण) पर्याप्त नहीं होंगे। ऐसा होता है, उदाहरण के लिए, जब आपकी कुंजी का प्रकार एक कस्टम प्रकार होता है और आप दो चाबियों को बराबर मानना ​​चाहते हैं, तब भी जब वे कस्टम प्रकार का एक ही उदाहरण नहीं हैं।

उदाहरण के लिए, यदि आपके कुंजी के रूप में सरल

रूप
class Point { 
    public int X { get; set; } 
    public int Y { get; set; } 
} 

है और आप दो Point दो चाहते बराबर पर विचार किया जाना आप Equals ओवरराइड करने के लिए की आवश्यकता होगी अगर उनकी X रों बराबर हैं और उनके Y रों तो बराबर हैं और GetHashCode

+0

किसी डिक्शनरी के संबंध में, बराबर और GetHashCode क्या होने की आवश्यकता है 1) मैं ऑब्जेक्ट को जगह में संपादित करता हूं और 'point.Y' के लिए' point.X' को स्वैप करता हूं? क्या मूल्य को हटा देना है, और फिर शब्दकोश में जोड़ा गया है? – LamonteCristo

2

एक उदाहरण यह है कि जब आपको एक समग्र कुंजी बनाने की आवश्यकता होती है (यह एक कुंजी है जिसमें डेटा का एक टुकड़ा शामिल है)। वह समग्र कुंजी एक कस्टम प्रकार होगा जिसे उन तरीकों को ओवरराइड करने की आवश्यकता होगी।

उदाहरण के लिए, मान लीजिए कि आपके पास पता रिकॉर्ड का एक मेमोरी कैश था और आप यह जांचना चाहते थे कि डेटाबेस को एक महंगी यात्रा बचाने के लिए कैश में कोई पता था या नहीं। आइए यह भी कहें कि उनके सड़क 1 और ज़िप कोड फ़ील्ड के संदर्भ में पते अद्वितीय हैं। आप कुछ इस तरह से अपने कैश लागू करना होगा:

class AddressCacheKey 
{ 
    public String StreetOne { get; set; } 
    public String ZipCode { get; set; } 

    // overrides for Equals and GetHashCode 
} 

और

static Dictionary<AddressCacheKey,Address> cache; 

के बाद से अपने AddressCacheKey प्रकार ओवरराइड करता है Equals और GetHashCode तरीकों वे शब्दकोश में एक महत्वपूर्ण लिए एक अच्छे उम्मीदवार हो सकता है और क्या तुम करोगी यह निर्धारित करने में सक्षम हो कि डेटा के एक से अधिक टुकड़ों के आधार पर रिकॉर्ड पुनर्प्राप्त करने के लिए आपको डेटाबेस में यात्रा करने की आवश्यकता है या नहीं।

1

आपके यहां दो प्रश्न हैं।

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

1. के साथ शुरू आप एक वर्ग है कि संभवतः किसी और के द्वारा इस्तेमाल किया जा सकता लिख ​​रहे हैं, तो चलो, तुम GetHashCode() और बराबर(), परिभाषित करना चाहते हैं जाएगा, जब संदर्भ बराबर() पर्याप्त नहीं है। यदि आप इसे किसी शब्दकोश में उपयोग करने की योजना नहीं बना रहे हैं, और यह आपके स्वयं के उपयोग के लिए है, तो मुझे GetHashCode() इत्यादि को छोड़ने का कोई कारण नहीं दिखता है

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

9

बस यह स्पष्ट करना: शब्दकोश निर्धारित करने के लिए दो चाबियाँ बराबर अर्थात हैं <TKey> कस्टम प्रकार आप GetHashCode() ध्यान से लागू करने के बारे ध्यान देना चाहिए की है GetHashCode का उपयोग करता है: वहाँ एक महत्वपूर्ण बात के बारे Dictionary<TKey, TValue> और GetHashCode() है। जैसा कि एंड्रयू हारे ने बताया कि यह आसान है, अगर आपके पास एक साधारण प्रकार है जो आपके कस्टम ऑब्जेक्ट को स्पष्ट रूप से पहचानता है। यदि आपके पास संयुक्त पहचानकर्ता है, तो यह थोड़ा और जटिल हो जाता है।

उदाहरण के रूप में TKey के रूप में एक जटिल संख्या पर विचार करें। एक जटिल संख्या इसके वास्तविक और इसके काल्पनिक भाग द्वारा निर्धारित की जाती है। दोनों सरल प्रकार के हैं उदा। double। लेकिन यदि आप दो जटिल संख्या बराबर हैं तो आप कैसे पहचानेंगे? आप अपने कस्टम कॉम्प्लेक्स प्रकार के लिए GetHashode() लागू करते हैं और पहचानने वाले दोनों भागों को गठबंधन करते हैं।

आपको बाद वाले here पर और पढ़ने के लिए मिलता है।

अद्यतन

Ergwun की टिप्पणी मैं Equals(object) और GetHashCode() की TKey के कार्यान्वयन के लिए विशेष सम्मान के साथ Dictionary<TKey, TValue>.Add के व्यवहार की जाँच के आधार पर। मैं को यह स्वीकार करना होगा कि मैं परिणामों से आश्चर्यचकित था।

को देखते हुए दो वस्तुओं k1 और प्रकार TKey की k2, दो मनमाना वस्तुओं v1 और प्रकार TValue की v2, और प्रकार Dictionary<TKey, TValue> के एक खाली शब्दकोश d, इस जब कुंजी के साथ d पहली और v2 की कुंजी k1 साथ v1 जोड़ने क्या होता है

k1.Equals(k2) k1.GetHashCode() == k2.GetHashCode() d.Add(k2, v2) 
false   false         ok 
false   true         ok 
true   false         ok 
true   true         System.ArgumentException 

कोन: k2 दूसरा (TKey.Equals(object) के कार्यान्वयन और TKey.GetHashCode() के आधार पर) भ्रम: मैं गलत था क्योंकि मैंने मूल रूप से दूसरा मामला सोचा था (जहां Equalsfalse देता है लेकिन दोनों प्रमुख वस्तुओं में एक ही हैश कोड है) ArgumentException उठाएगा। लेकिन चूंकि तीसरा मामला किसी भी तरह से शब्दकोश दिखाता है GetHashCode() का उपयोग करता है। वैसे भी यह अच्छी सलाह प्रतीत होती है कि दो ऑब्जेक्ट्स जो एक ही प्रकार के हैं और बराबर हैं, उन्हें यह सुनिश्चित करने के लिए एक ही हैश कोड वापस करना होगा कि उदाहरण Dictionary<TKey, TValue> सही तरीके से काम करते हैं।

+9

-1 शब्दकोश यह निर्धारित करने के लिए 'GetHashCode()' का उपयोग नहीं करता है कि दो कुंजी बराबर हैं या नहीं। यही है, एक शब्दकोश में अलग-अलग प्रविष्टियां हो सकती हैं जिनकी चाबियों में एक ही हैश कोड होता है। शब्दकोश कम कुशल हो सकता है, लेकिन यह अभी भी काम करेगा। – Ergwun

+2

+1 अद्यतन के लिए :) – Ergwun

+0

हां, आपको यह सुनिश्चित करना चाहिए कि समान वस्तुएं समान हैंश कोड लौटाएं (http://msdn.microsoft.com/en-us/library/ms182358.aspx देखें)। – Ergwun

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