2010-02-10 8 views
15

मुझे एक कस्टम ऑब्जेक्ट में समस्या है जिसे तालिका के लिए कुंजी की आवश्यकता है। मुझे एक अद्वितीय संख्यात्मक कुंजी उत्पन्न करने की आवश्यकता है। मुझे टकराव की समस्याएं आ रही हैं और मैं सोच रहा हूं कि क्या मैं मेरी मदद करने के लिए एक शब्दकोश का लाभ उठा सकता हूं। मान लें कि मेरे पास इस तरह की वस्तु है:.NET शब्दकोश टकराव को हल करता है?

class Thingy 
{ 
    public string Foo; 
    public string Bar; 
    public string Others; 
} 

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

public override bool Equals(object obj) 
{ 
    Thingy thing = (Thingy)obj; // yes I do type check first 
    return (this.Foo == thing.Foo && this.Bar == thing.Bar); 
} 

public override int GetHashCode() 
{ 
    return (this.Foo + this.Bar).GetHashCode(); // using default string impl 
} 

इसलिए यह अधिकांश भाग के लिए काम करता है, लेकिन दुर्लभ अवसर हैं जहां दो थिंगिस वास्तव में अलग हैं, एक ही हैश कोड है।

मेरा प्रश्न यह है: क्या मैं एक शब्दकोश <Thingy, int> जहां मैं अपने थिंगिस में डाल सकता हूं, और मेरी वास्तविक कुंजी के रूप में शब्दकोश से बाहर आने वाले क्रमिक मूल्य का उपयोग कर सकता हूं? मैं सोच रहा हूं कि डिक्शनरी, दुर्लभ हैश कोड टकराव का पता लगाने पर, मेरे बराबर विधि को कॉल करेगी, यह निर्धारित करेगी कि वस्तुएं वास्तव में अलग हैं, और उन्हें अलग-अलग स्टोर करें। मैं इसे देखकर इमेजिंग करता हूं, यह उस हैश के लिए एक बाल्टी दिखाई देगा और सही थिंगी की खोज करेगा, फिर तुलना के लिए बराबर का उपयोग कर।

क्या यह शब्दकोश के साथ मामला है, या यह केवल टकराव को हल करता है जहां हैश कोड अलग है, लेकिन (हैश% आकार) समान है? अगर यह काम नहीं करेगा, तो क्या हो सकता है?

उत्तर

25

हैश टकराव केवल प्रदर्शन को प्रभावित करता है, अखंडता नहीं।

एक सरल परीक्षण GetHashCode() को केवल 1 लौटने के लिए बदलना होगा; आप ध्यान दें कि शब्दकोश अभी भी ठीक से व्यवहार करता है, लेकिन किसी भी उचित डेटासेट के साथ, यह बहुत ही प्रदर्शन करेगा।

+0

बिंदु को चित्रित करने का अच्छा तरीका। – itowlson

18

हैश टकराव मुख्य रूप से प्रदर्शन को प्रभावित करेगा - सहीता नहीं। जब तक Equals() सही तरीके से व्यवहार करता है।

Dictionary आइटम को अलग-अलग "बाल्टी" में व्यवस्थित करने के तरीके के रूप में हैश कोड का उपयोग करता है। यदि बहुत से आइटम एक ही हैश कोड साझा करते हैं, तो आप प्रदर्शन समस्याओं में भाग ले सकते हैं। हालांकि, जब तक Equals() उदाहरणों के बीच सही ढंग से अंतर कर सकते हैं, तो आपको सही परिणाम मिलना चाहिए।

जहां हैश कोड परिणामस्वरूप परिवर्तनीय वस्तुओं के साथ समस्याएं हो सकती हैं। यदि Thingy कक्षा Foo या Bar शब्दकोश में किसी आइटम के लिए बदलने के लिए अनुमति देता है, तो आप इसे बाद के एक्सेस प्रयास में ढूंढने में विफल हो सकते हैं। ऐसा इसलिए है क्योंकि उत्पादित हैश कोड अब शब्दकोश में मूल्य को संग्रहीत करने के लिए उपयोग किए जाने वाले व्यक्ति से अलग है।

+0

यह वास्तव में किसी भी शब्दकोश के लिए सच है। सभी शब्दकोश प्रकार निरंतर कुंजी मानते हैं। – Joel

+0

म्यूटेबल ऑब्जेक्ट्स के लिए, आप आमतौर पर बेस ऑब्जेक्ट छोड़ना चाहते हैं। एक्वाल्स() विधि अकेले, क्योंकि यह संदर्भ समानता देता है। आप आम तौर पर परीक्षण मूल्य समानता के लिए == अधिभार चाहते हैं। तो यदि आप डिफ़ॉल्ट ऑब्जेक्ट छोड़ते हैं। एक्वाल्स() अकेले, आप विवादास्पद ऑब्जेक्ट्स को साइड इफेक्ट्स के बिना डिक्शनरी कुंजियों के रूप में उपयोग कर सकते हैं। – Bob

+2

गैर-अपरिवर्तनीय प्रकारों में ऑपरेटर == ओवरराइडिंग आमतौर पर अनुशंसित नहीं है। एमएसडीएन दस्तावेज वास्तव में उन मामलों को अस्वीकार करता है जहां आप 'ऑब्जेक्ट। एक्वाल्स()' और '==' ऑपरेटर को ओवरराइड करना चाहते हैं। http://msdn.microsoft.com/en-us/library/ms173147%28VS.80%29.aspx – LBushkin

1

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

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

+0

वास्तव में शब्दकोश का उपयोग करने के बारे में मेरा मतलब था कि मैं ऑब्जेक्ट को टोकन की कुंजी के रूप में संग्रहीत करता हूं, और फिर मूल्य के रूप में एक नया उच्चतम int संग्रहीत करता हूं, और उस तालिका का उपयोग मेरी तालिका की कुंजी के रूप में करता है। तो dict में मान अनुक्रमिक होंगे, और यदि मैंने कोई ऑब्जेक्ट देखा, तो मुझे तालिका के लिए अद्वितीय संख्यात्मक कुंजी मिल जाएगी। तो आंतरिक शब्दकोश संरचना अप्रासंगिक है। – Tesserex

+0

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