2010-06-09 15 views
8

मुझे बताया गया था कि सी # स्पेक में तारों को अपरिवर्तनीय बनाने के कई कारणों में से एक हैशटबल्स के मुद्दे से बचने के लिए, जब स्ट्रिंग कुंजियों के संदर्भों ने उनकी सामग्री को बदल दिया था।सी # शब्दकोश <> और म्यूटेबल कुंजियां

शब्दकोश <> प्रकार संदर्भ प्रकारों को कुंजी के रूप में उपयोग करने की अनुमति देता है। शब्दकोष बदली हुई कुंजी के मुद्दे से कैसे बचता है जो "गलत स्थान" मानों का कारण बनता है? जब किसी कुंजी के रूप में उपयोग किया जाता है तो ऑब्जेक्ट से बना एक सदस्यवार क्लोन होता है?

उत्तर

9

Dictionary<TKey,TValue> प्रकार उपयोगकर्ता द्वारा उपयोग की जाने वाली कुंजी को संशोधित करने के खिलाफ सुरक्षा करने का कोई प्रयास नहीं करता है। कुंजी को म्यूट करने में जिम्मेदार होने के लिए डेवलपर को पूरी तरह से छोड़ दिया जाता है।

यदि आप इस बारे में कुछ सोचते हैं तो यह वास्तव में केवल एकमात्र रास्ता है जो Dictionary<TKey,TValue> ले सकता है। ऑब्जेक्ट पर सदस्यवार क्लोन की तरह ऑपरेशन करने के निहितार्थ पर विचार करें। पूरी तरह से होने के लिए आपको एक गहरी क्लोन करने की आवश्यकता होगी क्योंकि कुंजी में संदर्भित ऑब्जेक्ट के लिए यह भी संभव होगा कि इसे उत्परिवर्तित किया जाए और इसलिए हैश कोड को प्रभावित करें। तो अब तालिका में उपयोग की जाने वाली हर कुंजी में उत्परिवर्तन के खिलाफ सुरक्षा के लिए इसका पूर्ण ऑब्जेक्ट ग्राफ़ क्लोन किया गया है। यह दोनों छोटी और संभवतः एक बहुत महंगा ऑपरेशन होगा।

+1

पाइथन हालांकि एक और तरीका चला गया और एक कैश कुंजी के रूप में परिवर्तनीय डेटा की अनुमति नहीं है। http://www.udacity.com/view#Course/cs212/CourseRev/apr2012/Unit/207010/Nugget/251006 –

5

Dictionary<> कक्षा एक परिवर्तनीय कुंजी वस्तु को बदलने के खिलाफ खुद को बचाने के लिए कुछ भी नहीं करती है। यह जानने के लिए आप पर निर्भर है कि आप जिस कुंजी को कुंजी के रूप में उपयोग कर रहे हैं वह म्यूटेबल है या नहीं, और यदि संभव हो तो इससे बचने के लिए।

3

यह इस स्थिति से नहीं बचा है। यह इस लागू करने के लिए बुला कोड पर निर्भर है:

जब तक एक वस्तु Dictionary<TKey, TValue> में एक महत्वपूर्ण के रूप में प्रयोग किया जाता है, यह अपने हैश मान प्रभावित करता है किसी भी तरह से बदल नहीं करना चाहिए। Dictionary<TKey, TValue> में प्रत्येक कुंजी शब्दकोश की समानता तुलनाकर्ता के अनुसार अद्वितीय होनी चाहिए। एक कुंजी null नहीं हो सकती है, लेकिन एक मान हो सकता है, यदि मान प्रकार TValue एक संदर्भ प्रकार है।

(MSDN से)

8

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

+0

यह एक अच्छा है।मुझे याद रखने के लिए धन्यवाद कि डिफ़ॉल्ट रूप से ऑब्जेक्ट के लिए GetHashCode उदाहरण पर आधारित है जो मुझे लगता है कि डेवलपर्स को बहुत समय बचाता है। –

+0

मूल्य समानता अर्थशास्त्र के साथ उत्परिवर्ती वर्ग प्रकार वैसे भी एक बुरा विचार की तरह लगते हैं। हालांकि कुछ अपवाद हैं (उदाहरण के लिए 'डबल', 'दशमलव ',' सूची । एन्यूमेरेटर 'इत्यादि), अधिकांश प्रकारों में .net को समानता (ऑब्जेक्ट)' लागू करने के लिए समानता इंगित करने के लिए; चूंकि अलग-अलग म्यूटेबल क्लास-टाइप आइटम कभी समकक्ष नहीं होते हैं, उन्हें खुद को 'बराबर' ('सूची ' का व्यवहार कभी नहीं करना चाहिए। एन्यूमेरेटर 'इस तथ्य से उत्पन्न होता है कि बॉक्स किए गए और अनबॉक्स किए गए मान प्रकारों में अलग-अलग अर्थशास्त्र होते हैं, लेकिन उन्हें साझा करने की आवश्यकता होती है वही 'बराबर 'विधि)। – supercat

3

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

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

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