GetHashCode सी # में दिशानिर्देश


136

मैंने आवश्यक C # 3.0 और .NET 3.5 पुस्तक में पढ़ा है कि:

GetHashCode () का किसी विशेष ऑब्जेक्ट के जीवन पर रिटर्न स्थिर होना चाहिए (समान मूल्य), भले ही ऑब्जेक्ट का डेटा बदल जाए। कई मामलों में, आपको इसे लागू करने के लिए विधि वापसी को कैश करना चाहिए।

क्या यह एक वैध दिशानिर्देश है?

मैंने .NET में कुछ जोड़े प्रकारों की कोशिश की है और वे इस तरह का व्यवहार नहीं करते हैं।


यदि संभव हो तो आप स्वीकृत उत्तर को बदलने पर विचार कर सकते हैं।
गिफ्फुगी 19

जवाबों:


93

जवाब ज्यादातर है, यह एक वैध दिशानिर्देश है, लेकिन शायद एक वैध नियम नहीं है। यह पूरी कहानी भी नहीं बताता है।

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

उदाहरण के लिए, ऑब्जेक्ट ए 1. का हैश लौटाता है, इसलिए यह हैश तालिका के बिन 1 में जाता है। फिर आप ऑब्जेक्ट ए को बदलते हैं जैसे कि यह 2. का एक हैश लौटाता है। जब कोई हैश टेबल इसे ढूंढता है, तो यह बिन 2 में दिखता है और यह नहीं मिल सकता है - ऑब्जेक्ट बिन में अनाथ है 1. यही कारण है कि हैश कोड होना चाहिए ऑब्जेक्ट के जीवनकाल के लिए परिवर्तन नहीं , और सिर्फ एक कारण है कि GetHashCode कार्यान्वयन लिखना बट में दर्द है।

अपडेट
एरिक लिपर्ट ने एक ब्लॉग पोस्ट किया है , जिसमें उत्कृष्ट जानकारी दी गई है GetHashCode

अतिरिक्त अपडेट
मैंने ऊपर कुछ बदलाव किए हैं:

  1. मैंने दिशानिर्देश और नियम के बीच अंतर किया।
  2. मैंने "वस्तु के जीवनकाल के लिए" मारा।

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

जब आप "ऑब्जेक्ट के जीवनकाल के लिए" देखते हैं, तो आपको उस समय के लिए "पढ़ना चाहिए जब ऑब्जेक्ट को हैश टेबल के साथ सहयोग करने की आवश्यकता होती है" या इसी तरह की। ज्यादातर चीजों की तरह, GetHashCodeनियमों को तोड़ने के बारे में जानने के बारे में है।


1
आप परिवर्तनशील प्रकारों के बीच समानता कैसे निर्धारित करते हैं?
जॉन बी

9
समानता का निर्धारण करने के लिए आपको GetHashCode का उपयोग नहीं करना चाहिए।
जेएसबी JS

4
@JS बैंग्स - MSDN से: GetHashCode को ओवरराइड करने वाले व्युत्पन्न वर्ग को यह गारंटी देने के लिए भी बराबरी करनी होगी कि समान मानी जाने वाली दो वस्तुओं का समान हैश कोड है; अन्यथा, हैशटेबल प्रकार सही ढंग से काम नहीं कर सकता है।
जॉन बी

3
@ जोबन वेंज: दो चीजें। सबसे पहले, माइक्रोसॉफ्ट ने भी GetHashCode को हर कार्यान्वयन में सही नहीं पाया है। दूसरा, मूल्य प्रकार आम तौर पर मौजूदा उदाहरण के संशोधन के बजाय हर मूल्य के एक नए उदाहरण के साथ अपरिवर्तनीय होता है।
जेफ येट्स

17
चूंकि a.Equals (b) का मतलब यह होना चाहिए कि a.GetHashCode () == b.GetHashCode (), हैश कोड को सबसे अधिक बार बदलना होगा यदि समानता तुलना के लिए उपयोग किए गए डेटा को बदल दिया जाए। मैं कहता हूँ कि समस्या GetHashCode नहीं है जो परस्पर डेटा पर आधारित है। समस्या हैश टेबल कीज़ (और वास्तव में उन्हें उत्परिवर्तित करना) के रूप में उत्परिवर्तनीय वस्तुओं का उपयोग कर रही है। क्या मै गलत हु?
निकल्स

120

यह एक लंबा समय हो गया है, लेकिन फिर भी मुझे लगता है कि इस सवाल का सही जवाब देना अभी भी आवश्यक है, जिसमें व्हॉट्स और हॉव्स के बारे में स्पष्टीकरण भी शामिल है। अब तक का सबसे अच्छा जवाब है MSDN का हवाला देते हुए एक - अपने नियम बनाने की कोशिश मत करो, एमएस लोग जानते थे कि वे क्या कर रहे थे।

लेकिन पहली चीजें पहली: गाइडलाइन के रूप में प्रश्न में उद्धृत गलत है।

अब चाबुक - उनमें से दो हैं

पहला क्यों : यदि हैशकोड की गणना एक तरह से की जाती है, कि यह किसी वस्तु के जीवनकाल के दौरान नहीं बदलता है, भले ही वह वस्तु अपने आप बदल जाए, इससे बराबरी का अनुबंध टूट जाएगा।

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

दूसरे वाक्य को अक्सर गलत समझा जाता है, "एकमात्र नियम यह है, कि वस्तु निर्माण के समय, समान वस्तुओं का हैशकोड बराबर होना चाहिए"। वास्तव में पता नहीं क्यों, लेकिन यह भी यहाँ सबसे जवाब के सार के बारे में है।

एक नाम वाली दो वस्तुओं के बारे में सोचें, जहाँ नाम का उपयोग समान विधि में किया जाता है: समान नाम -> एक ही बात। इंस्टेंस ए बनाएँ: नाम = जो इंस्टेंस बी बनाएं: नाम = पीटर

Hashcode A और Hashcode B की संभावना एक समान नहीं होगी। अब क्या होगा, जब उदाहरण B का नाम बदलकर Joe कर दिया जाए?

प्रश्न से दिशानिर्देश के अनुसार, बी का हैशकोड नहीं बदलेगा। इसका परिणाम यह होगा: A.Equals (B) ==> सत्य लेकिन एक ही समय में: A.GetHashCode () == B.GetHashCode () ==> गलत।

लेकिन वास्तव में यह व्यवहार बराबरी और हैशकोड-अनुबंध द्वारा स्पष्ट रूप से मना किया गया है।

दूसरा क्यों : जबकि यह है - बेशक - सच है, हैशकोड में परिवर्तन हैशेड सूचियों और हैशकोड का उपयोग करके अन्य वस्तुओं को तोड़ सकता है, रिवर्स भी सच है। सबसे खराब स्थिति में हैशकोड नहीं बदलने से हैशेड सूचियाँ मिलेंगी, जहाँ सभी विभिन्न वस्तुओं में समान हैशकोड होगा और उसी हैश बिन में भी होगा - तब होता है जब वस्तुओं को एक मानक मान के साथ आरम्भ किया जाता है, उदाहरण के लिए।


अब हाउज़ वेल में आने पर, पहली नज़र में, एक विरोधाभास प्रतीत होता है - किसी भी तरह, कोड टूट जाएगा। लेकिन न तो समस्या परिवर्तित या अपरिवर्तित हैशकोड से आती है।

MSDN में समस्याओं का स्रोत अच्छी तरह से वर्णित है:

MSDN की हैशटेबल प्रविष्टि से:

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

इसका मतलब यह है:

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

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

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

ठीक है, साथ ही साथ क्या कहा जाना चाहिए: ऐसे मामले हैं, जहां उत्परिवर्तित डेटा के साथ ऑब्जेक्ट होना संभव है, जहां हैशकोड फिर भी अपरिवर्तित होता है, जब ऑब्जेक्ट डेटा को बदल दिया जाता है, तो बराबर और हैशकोड-अनुबंध का उल्लंघन किए बिना।

हालाँकि इसके लिए यह आवश्यक है कि समतुल्य-विधि उत्परिवर्तनीय डेटा पर भी आधारित न हो। इसलिए, यदि मैं एक ऑब्जेक्ट लिखता हूं, और एक गेटहेडकोड ​​विधि बनाता हूं जो केवल एक बार एक मूल्य की गणना करता है और बाद में कॉल करने के लिए इसे वापस करने के लिए ऑब्जेक्ट के अंदर संग्रहीत करता है, तो मुझे फिर से: बिल्कुल, एक समान विधि बनाना होगा, जो इसका उपयोग करेगा तुलना के लिए संग्रहीत मान, ताकि A.Equals (B) कभी भी असत्य से सत्य में परिवर्तित न हो। अन्यथा, अनुबंध टूट जाएगा। इसका परिणाम आमतौर पर यह होगा कि समान पद्धति का कोई मतलब नहीं है - यह मूल संदर्भ के बराबर नहीं है, लेकिन यह न तो मूल्य के बराबर है। कभी-कभी, यह अभिप्रेत व्यवहार (अर्थात ग्राहक रिकॉर्ड) हो सकता है, लेकिन आमतौर पर ऐसा नहीं होता है।

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

(वैसे: यह सब C # oder .NET विशिष्ट नहीं है - यह सभी हैशटेबल कार्यान्वयनों की प्रकृति में है, या आम तौर पर किसी भी अनुक्रमित सूची के अधिक, कि वस्तुओं के डेटा को पहचानना कभी नहीं बदलना चाहिए, जबकि वस्तु सूची में है । यदि यह नियम टूटा हुआ है, तो अप्रत्याशित और अप्रत्याशित व्यवहार होगा। कहीं न कहीं, सूची क्रियान्वयन हो सकता है, जो सूची के अंदर सभी तत्वों की निगरानी करते हैं और सूची को स्वचालित रूप से संशोधित करते हैं - लेकिन उन का प्रदर्शन निश्चित रूप से सबसे अच्छा होगा।)


23
इस विस्तृत विवरण के लिए +1 (यदि मैं कर सकता हूं तो अधिक दे दूंगा)
ओलिवर

5
+1 यह निश्चित रूप से क्रिया स्पष्टीकरण के कारण बेहतर उत्तर है! :)
जो

9

से MSDN

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

किसी ऑब्जेक्ट के लिए GetHashCode विधि को लगातार उसी हैश कोड को वापस करना चाहिए जब तक कि ऑब्जेक्ट राज्य के लिए कोई संशोधन नहीं होता है जो ऑब्जेक्ट के बराबर विधि के रिटर्न मूल्य को निर्धारित करता है। ध्यान दें कि यह केवल किसी एप्लिकेशन के वर्तमान निष्पादन के लिए सही है, और यदि एप्लिकेशन फिर से चलाया जाता है तो एक अलग हैश कोड वापस किया जा सकता है।

सर्वश्रेष्ठ प्रदर्शन के लिए, हैश फ़ंक्शन को सभी इनपुट के लिए एक यादृच्छिक वितरण उत्पन्न करना चाहिए।

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


संपादित करें :

MSDN से भी:

GetHashCode को ओवरराइड करने वाली व्युत्पन्न कक्षाएं भी समान को ओवरराइड करने की गारंटी देती हैं कि समान माना जाने वाला दो ऑब्जेक्ट एक ही हैश कोड है; अन्यथा, हैशटेबल प्रकार सही ढंग से काम नहीं कर सकता है।

से MSDN के hashtable प्रविष्टि :

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

जिस तरह से मैंने यह पढ़ा है कि उत्परिवर्तित वस्तुओं को अलग-अलग हैशकोड वापस करना चाहिए क्योंकि उनके मान परिवर्तन होते हैं, जब तक कि वे एक हैवेबल में उपयोग के लिए डिज़ाइन नहीं किए जाते हैं।

System.Drawing.Point के उदाहरण में, वस्तु परिवर्तनशील है, और करता है एक अलग hashCode जब एक्स या वाई मूल्य परिवर्तन लौट आते हैं। यह एक गरीब उम्मीदवार के रूप में इस्तेमाल किया जा करने के लिए एक हैशटेबल में होता है।


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

@skolima - MSDN प्रलेखन उस के साथ असंगत है। म्यूटेबल ऑब्जेक्ट GetHashCode () को लागू कर सकते हैं, और ऑब्जेक्ट के मूल्य में परिवर्तन के रूप में अलग-अलग मान वापस करना चाहिए। हैशटेबल्स को अपरिवर्तनीय कुंजियों का उपयोग करना चाहिए। इसलिए, आप हैशटेबल के अलावा किसी और चीज के लिए GetHashCode () का उपयोग कर सकते हैं।
जॉन बी

9

मुझे लगता है कि GetHashcode के बारे में प्रलेखन थोड़ा भ्रमित करने वाला है।

एक तरफ, MSDN कहता है कि किसी वस्तु का हैशकोड कभी नहीं बदलना चाहिए, और स्थिर रहना चाहिए दूसरी तरफ, MSDN यह भी कहता है कि GetHashcode का रिटर्न मान 2 ऑब्जेक्ट के बराबर होना चाहिए, यदि उन 2 ऑब्जेक्ट को समान माना जाता है।

MSDN:

एक हैश फ़ंक्शन में निम्न गुण होने चाहिए:

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

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

public class SomeThing
{
      public string Name {get; set;}

      public override GetHashCode()
      {
          return Name.GetHashcode();
      }

      public override Equals(object other)
      {
           SomeThing = other as Something;
           if( other == null ) return false;
           return this.Name == other.Name;
      }
}

यह कार्यान्वयन पहले से ही उन नियमों का उल्लंघन करता है जो MSDN में पाए जा सकते हैं। मान लीजिए कि आपके पास इस वर्ग के 2 उदाहरण हैं; Inst1 की नाम संपत्ति 'Pol' पर सेट है, और Inst2 की नाम संपत्ति 'Piet' पर सेट है। दोनों उदाहरण एक अलग हैशकोड लौटाते हैं, और वे समान नहीं हैं। अब, मान लीजिए कि मैंने उदाहरण 2 का नाम बदलकर 'पोल' कर दिया है, तो, मेरी समान पद्धति के अनुसार, दोनों उदाहरण समान होने चाहिए, और MSDN के नियमों में से एक के अनुसार, उन्हें समान हैशकोड वापस करना चाहिए।
हालाँकि, यह नहीं किया जा सकता है, क्योंकि inst2 का हैशकोड बदल जाएगा, और MSDN बताता है कि यह अनुमति नहीं है।

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

एक और बात जो ध्यान में आती है:
किस 'सत्र' के दौरान (मुझे वास्तव में यह नहीं पता है कि मुझे इसे कैसे कॉल करना चाहिए) 'गेटहैशकोड' को निरंतर मूल्य वापस करना चाहिए। मान लीजिए कि आप अपना आवेदन खोलते हैं, DB (निकाय) से किसी वस्तु का एक उदाहरण लोड करते हैं, और उसका हैशकोड प्राप्त करते हैं। यह एक निश्चित संख्या लौटाएगा। एप्लिकेशन को बंद करें, और उसी इकाई को लोड करें। क्या यह आवश्यक है कि इस बार हैशकोड का वही मूल्य हो जब आपने पहली बार इकाई को लोड किया हो? IMHO, नहीं।


1
आपका उदाहरण जेफ येट्स का कहना है कि आप उत्परिवर्तित डेटा पर हैश कोड को आधार नहीं बना सकते। आप किसी शब्दकोश में एक उत्परिवर्तनीय वस्तु को नहीं चिपका सकते हैं और उम्मीद करते हैं कि यह अच्छी तरह से काम करेगा अगर हैश कोड उस वस्तु के परस्पर मूल्यों पर आधारित हो।
ओगरे Psalm33

3
मैं यह नहीं देख पा रहा हूँ कि MSDN नियम का उल्लंघन कहाँ हुआ है? नियम स्पष्ट रूप से कहता है: किसी ऑब्जेक्ट के लिए GetHashCode विधि को लगातार उसी हैश कोड को वापस करना चाहिए जब तक कि ऑब्जेक्ट राज्य के लिए कोई संशोधन नहीं होता है जो ऑब्जेक्ट के बराबर विधि के वापसी मूल्य को निर्धारित करता है । इसका मतलब यह है कि
Inst2 का हैशकोड

8

यह अच्छी सलाह है। ब्रायन पेपिन ने इस मामले पर क्या कहा है:

इसने मुझे एक से अधिक बार ट्रिप किया है: सुनिश्चित करें कि GetHashCode हमेशा एक उदाहरण के जीवन भर में समान मूल्य लौटाता है। याद रखें कि अधिकांश हैशटेबल कार्यान्वयन में "बकेट" की पहचान करने के लिए हैश कोड का उपयोग किया जाता है। यदि किसी ऑब्जेक्ट की "बकेट" बदल जाती है, तो हैशटेबल आपकी ऑब्जेक्ट को खोजने में सक्षम नहीं हो सकता है। ये खोजने के लिए बहुत कठिन कीड़े हो सकते हैं, इसलिए इसे पहली बार सही करें।


मैंने इसे वोट नहीं दिया, लेकिन मुझे लगता है कि दूसरों ने ऐसा किया क्योंकि यह एक ऐसा उद्धरण है जो पूरी समस्या को कवर नहीं करता है। प्रिटेंड स्ट्रिंग्स परस्पर थे, लेकिन हैश कोड नहीं बदले। आप "बॉब" बनाते हैं, इसे हैशटेब में एक कुंजी के रूप में उपयोग करते हैं, और फिर इसे "फिल" के लिए बदल देते हैं। अगला एक नया स्ट्रिंग "फिल" बनाएं। यदि आप तब कुंजी "फिल" के साथ हैश तालिका प्रविष्टि की तलाश करते हैं, तो आपके द्वारा मूल रूप से डाली गई वस्तु नहीं मिलेगी। यदि किसी ने "बॉब" पर खोज की है, तो यह पाया जाएगा, लेकिन आपको एक मूल्य मिलेगा जो अब सही नहीं हो सकता है। या तो उन कुंजियों का उपयोग करने के लिए मेहनती हों, जो परस्पर परिवर्तनशील हों, या खतरों से अवगत हों।
एरिक टटलमैन

@EricTuttleman: क्या मैं एक ढांचे के लिए नियम लिख रहा था, मैंने निर्दिष्ट किया होगा कि किसी भी जोड़ी वस्तुओं के लिए Xऔर Y, एक बार X.Equals(Y)या Y.Equals(X)बुलाया गया है, सभी भविष्य की कॉल को एक ही परिणाम प्राप्त करना चाहिए। यदि कोई समानता की कुछ अन्य परिभाषा का उपयोग करना चाहता है, तो एक का उपयोग करें EqualityComparer<T>
सुपरकैट

5

सीधे अपने प्रश्न का उत्तर नहीं दे रहा है, लेकिन - यदि आप रेस्पर का उपयोग करते हैं, तो यह मत भूलो कि इसमें एक विशेषता है जो आपके लिए एक उचित GetHashCode कार्यान्वयन (और साथ ही समान विधि) उत्पन्न करता है। आप निश्चित रूप से निर्दिष्ट कर सकते हैं कि हैशकोड की गणना करते समय कक्षा के किन सदस्यों को ध्यान में रखा जाएगा।


धन्यवाद, वास्तव में मैंने कभी भी Resharper का उपयोग नहीं किया है, लेकिन मैं इसे अक्सर उल्लेखित देखता रहता हूं, इसलिए मुझे इसे आज़माना चाहिए।
जोन वेंज

यदि किसी के पास +1 रिचार्ज होता है तो वह एक अच्छा गेटहैशकोड लागू करता है।
57megaMan

5

मार्क ब्रूक्स के इस ब्लॉग पोस्ट को देखें:

VTO, RTO और GetHashCode () - ओह, माय!

और फिर अनुवर्ती पोस्ट की जांच करें (जैसा कि मैं नया हूं, लिंक नहीं कर सकता, लेकिन initlal लेख में एक लिंक है) जो आगे चर्चा करता है और प्रारंभिक कार्यान्वयन में कुछ छोटी कमजोरियों को शामिल करता है।

यह वह सब कुछ था जो मुझे GetHashCode () क्रियान्वयन के बारे में जानने के लिए आवश्यक था, वह कुछ अन्य उपयोगिताओं के साथ, लघु सोने में भी अपनी पद्धति का डाउनलोड प्रदान करता है।


4

हैशकोड कभी नहीं बदलता है, लेकिन यह समझना भी महत्वपूर्ण है कि हाशकोड कहां से आ रहा है।

यदि आपकी वस्तु मूल्य शब्दार्थ का उपयोग कर रही है, तो वस्तु की पहचान उसके मूल्यों (जैसे स्ट्रिंग, रंग, सभी संरचनाएं) द्वारा परिभाषित की जाती है। यदि आपकी वस्तु की पहचान उसके सभी मूल्यों से स्वतंत्र है, तो हाशकोड की पहचान उसके मूल्यों के सबसेट से की जाती है। उदाहरण के लिए, आपका StackOverflow प्रविष्टि डेटाबेस में कहीं संग्रहीत है। यदि आप अपना नाम या ईमेल बदलते हैं, तो आपकी ग्राहक प्रविष्टि वही रहती है, हालांकि कुछ मान बदल गए हैं (अंततः आप आमतौर पर कुछ लंबी ग्राहक आईडी द्वारा पहचाने जाते हैं)।

तो संक्षेप में:

मान प्रकार शब्दार्थ - हैशकोड को मूल्यों द्वारा परिभाषित किया जाता है संदर्भ प्रकार शब्दार्थ - हैशकोड को कुछ आईडी द्वारा परिभाषित किया गया है

मेरा सुझाव है कि आप एरिक इवांस द्वारा डोमेन ड्रिवेन डिज़ाइन पढ़ते हैं, जहां वह संस्थाओं बनाम मूल्य प्रकारों में जाता है (जो कि कम या ज्यादा मैंने ऊपर करने का प्रयास किया है) अगर यह अभी भी समझ में नहीं आता है।


यह वास्तव में सही नहीं है। किसी विशेष उदाहरण के लिए हैश कोड स्थिर रहना चाहिए। मूल्य प्रकारों के मामले में, यह अक्सर ऐसा होता है कि प्रत्येक मान एक अद्वितीय उदाहरण होता है और इसलिए, हैश बदलता दिखाई देता है, लेकिन वास्तव में इसका नया उदाहरण है।
जेफ येट्स

आप सही हैं, मान प्रकार अपरिवर्तनीय हैं, इसलिए वे बदलते रहते हैं। अच्छी पकड़।
14

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.