यह एक लंबा समय हो गया है, लेकिन फिर भी मुझे लगता है कि इस सवाल का सही जवाब देना अभी भी आवश्यक है, जिसमें व्हॉट्स और हॉव्स के बारे में स्पष्टीकरण भी शामिल है। अब तक का सबसे अच्छा जवाब है 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 विशिष्ट नहीं है - यह सभी हैशटेबल कार्यान्वयनों की प्रकृति में है, या आम तौर पर किसी भी अनुक्रमित सूची के अधिक, कि वस्तुओं के डेटा को पहचानना कभी नहीं बदलना चाहिए, जबकि वस्तु सूची में है । यदि यह नियम टूटा हुआ है, तो अप्रत्याशित और अप्रत्याशित व्यवहार होगा। कहीं न कहीं, सूची क्रियान्वयन हो सकता है, जो सूची के अंदर सभी तत्वों की निगरानी करते हैं और सूची को स्वचालित रूप से संशोधित करते हैं - लेकिन उन का प्रदर्शन निश्चित रूप से सबसे अच्छा होगा।)