2011-08-09 12 views
19

मैं एक शब्दकोश कुंजी के रूप में एक कस्टम वस्तु का उपयोग करना चाहते, मुख्य रूप से, मैं कुछ इस तरह है: (मैं .net 4.0 उपयोग नहीं कर सकते तो मैं tuples नहीं है)उपयोग कस्टम वस्तु के रूप में शब्दकोश कुंजी

class Tuple<A, B> : IEquatable<Tuple<A,B>> 
{ 
    public A AValue { get; set; } 
    public B BValue { get; set; } 

    public Tuple(A a, B b){ AValue = a; BValue = b; } 

    public bool Equals(Tuple<A, B> tuple) 
    { 
    return tuple.AValue.Equals(AValue) && tuple.BValue.Equals(BValue); 
    } 

    public bool Equals(object o) 
    { 
    return this.Equals(o as Tuple<A,B>); 
    } 
} 

मैं फिर ऐसा कुछ करता हूं।

var boolmap = new Dictionary<Tuple<bool, bool>, string>(); 
    boolmap.Add(new Tuple<bool,bool>(true, true), "A"); 
    boolmap.Add(new Tuple<bool,bool>(true, false), "B"); 
    boolmap.Add(new Tuple<bool,bool>(false, true), "C"); 
    boolmap.Add(new Tuple<bool,bool>(false, false), "D"); 
    var str = boolmap[new Tuple<bool,bool>(true, false)]; 

मुझे अंतिम पंक्ति में एक KeyNotFound अपवाद मिलता है। ऐसा क्यों है ? क्या यह पर्याप्त नहीं है कि मैं IEquatable लागू करता हूँ?

धन्यवाद

+1

आपके पास हैश कोड कार्यान्वयन कहां है? यदि आप बराबर डालते हैं तो आपको हमेशा हैश कोड प्राप्त होना चाहिए – Manatherin

+7

आपका कोड आपको एक चेतावनी देता है, और किसी कारण से। जब आप उस चेतावनी को ठीक करते हैं, तो आपको एक और चेतावनी मिल जाएगी - और जब आप इसे ठीक करेंगे, तो आपका कोड काम करेगा। चेतावनियों को कभी अनदेखा न करें। –

+0

आप देख सकते थे: [उपयोग-ए-ऑब्जेक्ट-ए-जेनरिक-डिक्शनरी-की-इन-नेट] (http: // stackoverflow।कॉम/प्रश्न/634826/उपयोग-ए-ऑब्जेक्ट-ए-जेनरिक-डिक्शनरी-की-इन-नेट) – nawfal

उत्तर

29

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

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

आपके मामले में एक साधारण कार्यान्वयन हो सकता है:

public override int GetHashCode() 
{ 
    return AValue.GetHashCode()^BValue.GetHashCode(); 
} 

ध्यान दें कि यह हो सकता है परीक्षण करने के लिए एक अच्छा विचार हो सकता है कि AValue या BValuenull हैं। (यह जब से तुम सामान्य प्रकार A और B विवश नहीं है कुछ हद तक जटिल हो जाएगा, तो आप सिर्फ null के मूल्यों की तुलना नहीं कर सकते हैं -। प्रकार मूल्य प्रकार हो सकता है, उदाहरण के लिए)

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


ध्यान दें कि आप EqualityComparer<A>.Default.GetHashCode(AValue) का उपयोग (और BValue के लिए समान) यहाँ कर सकता है, के रूप में है कि एक अशक्त जांच की आवश्यकता को समाप्त होगा।

+0

मैं जोड़ता हूं कि आपके ऑब्जेक्ट को सही ढंग से व्यवहार करने के लिए रखने के लिए मैंडोरी नियमों का बहुत महत्वपूर्ण सेट है शब्दकोश के भीतर। [कार्यान्वयन बराबर()] (http://geekswithblogs.net/gmamaladze/archive/2010/11/27/implementing-the-equals-method-in-.net-and--linear-algebra.aspx) [लागू करने पर एमएसडीएन बराबर()] (http://msdn.microsoft.com/en-us/library/336aedhh.aspx) –

+1

यहां एक और उत्कृष्ट संदर्भ: http://blogs.msdn.com/b/ericlippert/archive /2011/02/28/guidelines-and-rules-for-gethashcode.aspx – LukeH

0

मैं सिर्फ GetHashCode फ़ंक्शन को ओवरराइड कर रहा था, लेकिन ऐसा लगता है कि GetHashCode समान मान लौटा, अद्यतन नहीं हुआ। Equals होने के साथ-साथ, सबकुछ मजेदार और बेकार है

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