2009-07-21 10 views
10

क्या मुझे यह जांचना चाहिए कि में विशेष कुंजी मौजूद है या नहीं, अगर मुझे यकीन है कि इसे एक्सेस करने के लिए कोड तक पहुंचने तक मुझे शब्दकोश में जोड़ा जाएगा?क्या मुझे यह जांचना चाहिए कि इसे एक्सेस करने से पहले शब्दकोश में विशेष कुंजी मौजूद है या नहीं?

दो तरीके मैं शब्दकोश

  1. ContainsKey विधि जाँच में मूल्य का उपयोग कर सकते हैं। यदि यह सत्य लौटाता है तो मैं शब्दकोश वस्तु के सूचकांक [कुंजी] का उपयोग कर उपयोग करता हूं।

या

  1. TryGetValue जो बाहर पैरामीटर के माध्यम से सही या गलत के साथ ही वापसी मान वापस आ जाएगी।

(2 अगर मैं मूल्य प्राप्त करना चाहते हैं 1 की तुलना में बेहतर प्रदर्शन करेंगे। Benchmark।)

लेकिन अगर मुझे यकीन है कि समारोह जो वैश्विक शब्दकोश तक पहुँच रहा है निश्चित रूप से कुंजी होगा तो मैं अभी भी जांच होनी चाहिए हूँ TryGetValue का उपयोग करके या जांच किए बिना मुझे इंडेक्सर [] का उपयोग करना चाहिए।

या मुझे कभी यह नहीं मानना ​​चाहिए और हमेशा जांचना चाहिए?

उत्तर

18

अगर कुंजी मौजूद है तो सूचकांक का उपयोग करें - यदि यह मौजूद नहीं है, तो यह एक उचित अपवाद फेंक देगा, जो सही व्यवहार है यदि कुंजी की अनुपस्थिति एक बग इंगित करती है।

यदि यह मौजूद होने के लिए कुंजी के लिए मान्य है, तो इसके बजाय TryGetValue का उपयोग करें और तदनुसार प्रतिक्रिया दें।

(इसके अलावा एक साझा शब्दकोश सुरक्षित रूप से पहुँचने के बारे में मार्क की सलाह लागू होते हैं।)

+1

एक लापता कुंजी अक्सर एक और समस्या का संकेत है। यदि आप जानते हैं कि समस्या क्या है और एक और उपयोगी संदेश प्रदान कर सकती है, तो आपको अपने स्वयं के अपवाद को फेंकने पर विचार करना चाहिए क्योंकि 'KeyNotFoundException' के साथ संदेश कभी-कभी संकुचित करना मुश्किल होता है। –

+0

यह निश्चित रूप से उपयोगी होगा यदि KeyNotFoundException ने भी कुंजी दी - लेकिन इसके अलावा, केवल स्टैक ट्रेस सामान्य रूप से मेरे लिए पर्याप्त है। आप इसे कितना दूर ले लेंगे: नलिका के लिए हर संभावित शून्य संदर्भ (केवल तर्क नहीं, बल्कि आंतरिक रूप से गैर-शून्य होने की अपेक्षा) की जांच करना और उनमें से प्रत्येक पर एक कस्टम अपवाद फेंकना? आंतरिक असंगतता के मामलों में ढांचे के बिट्स द्वारा हमेशा अपवादों को फेंक दिया जाएगा: यदि आप उनमें से प्रत्येक को अनुमान लगाने का प्रयास करते हैं, तो कोड प्रगति करने से त्रुटि मामलों के बारे में अधिक होता है। –

10

यदि शब्दकोश वैश्विक (स्थिर/साझा) है, तो आपको इसकी पहुंच सिंक्रनाइज़ करना चाहिए (यह महत्वपूर्ण है, अन्यथा आप इसे भ्रष्ट कर सकते हैं)।

भले ही आपका धागा केवल डेटा पढ़ रहा है, इसे अन्य धागे के ताले का सम्मान करने की आवश्यकता है जो इसे संपादित कर सकते हैं।

हालांकि; यदि आप यह सुनिश्चित करें कि आइटम नहीं है कर रहे हैं, इंडेक्सर ठीक किया जाना चाहिए:

Foo foo; 
lock(syncLock) { 
    if(!data.TryGetValue(key, out foo)) { 
     foo = new Foo(key); 
     data.Add(key, foo); 
    } 
} 
// use foo... 

यहाँ हम केवल जोड़ें:

Foo foo; 
lock(syncLock) { 
    foo = data[key]; 
} 
// use foo... 

अन्यथा, एक उपयोगी पैटर्न की जाँच करें और एक ही ताला में जोड़ने के लिए है आइटम अगर यह वहां नहीं था ... लेकिन उसी लॉक के अंदर

+0

अच्छा, लेकिन मुझे नहीं लगता कि यह सवाल था? मुझे समवर्तीता का कोई संदर्भ नहीं दिख रहा है? :) – Thorarin

+0

"वैश्विक शब्दकोश" - बस मुझे एक दिए गए पथ को सेट करें। अगर मेरी समझ गलत है तो ओपी सिर्फ इस जवाब को अनदेखा कर सकता है ;- –

+0

शब्दकोश से डेटा पढ़ने के दौरान हमें लॉक लेने की आवश्यकता क्यों है? क्या यह कुछ सीमा के बाद शब्दकोश विस्तार/पुनः-हैशिंग के कारण है? –

2

हमेशा जांचें। नेवर से नेवर। मुझे लगता है कि आपका आवेदन उस प्रदर्शन को महत्वपूर्ण नहीं है जिसे आपको चेकिंग समय को सहेजना होगा।

टीआईपी: यदि आप जांच नहीं करना चाहते हैं, तो कम से कम Debug.Assert (dict.ContainsKey (कुंजी) का उपयोग करें; यह केवल डीबग मोड में संकलित किया जाएगा, आपके रिलीज बिल्ड में यह शामिल नहीं होगा। इस तरह आप कम से कम जांच कर सकते हैं जब डीबगिंग।

फिर भी: यदि संभव हो तो, बस इसे जाँच :-)

संपादित करें: वहाँ कुछ गलतफहमी यहाँ किया गया है। "हमेशा जांचें" से मेरा मतलब न केवल किसी जगह का उपयोग करना था। एक अपवाद को सही तरीके से संभालना भी इसमें शामिल था। तो, अधिक सटीक होने के लिए: कभी भी कुछ भी नहीं लिया जाता है, अप्रत्याशित होने की उम्मीद है। ContainsKey द्वारा जांचें या संभावित अपवाद को संभालें, लेकिन तत्व निहित नहीं होने पर कुछ करें।

+4

का उपयोग करना बहुत आसान है, मैं इससे असहमत हूं। यदि कुंजी मौजूद है और नहीं है, तो सही व्यवहार एक अपवाद फेंकना है, हां? और यह वही है जो सूचकांक करता है - तो उस व्यवहार का उपयोग क्यों न करें? इसके अतिरिक्त, मैं डीबग और रिलीज बिल्ड के बीच व्यवहार बदलने पर उत्सुक नहीं हूं ... यह मुझे समस्याओं के लिए नुस्खा की तरह लगता है। –

+0

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

+0

मैं जॉन से सहमत हूं, आप केवल यह जांचते हैं कि यह कब हो सकता है या नहीं भी हो सकता है, अगर आप निश्चित हैं कि यह वहां होना चाहिए तो सही पथ अपवाद को फेंकने और उसे तदनुसार संभालने की अनुमति देना है। – James

0

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

संपादित करें: जैसा कि जॉन ने कहा था, अगर आपको पता है कि इसमें हमेशा कुंजी होगी, तो आप इसे अनुक्रमित कर सकते हैं और इसे उपयुक्त अपवाद फेंक सकते हैं। हालांकि, अगर आप इसे एक विस्तृत संदेश के साथ फेंक कर बेहतर संदर्भ जानकारी प्रदान कर सकते हैं, तो यह बेहतर होगा।

0

प्रदर्शन बिंदु से इस पर विचार की 2 ट्रेनें हैं।

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

2) यदि आपको विश्वास है कि आइटम 99% समय में मौजूद होगा, तो इसे एक्सेस करने से पहले इसके अस्तित्व की जांच न करें। 1% बार जब यह अस्तित्व में नहीं होता है, तो एक अपवाद फेंक दिया जाएगा लेकिन आपने जांच के द्वारा 99% समय के लिए समय बचाया है।

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

+0

मुझे नहीं लगता कि यह वास्तव में प्रदर्शन के बारे में होना चाहिए। यह शुद्धता के बारे में होना चाहिए: यदि सही स्थितियों में कुंजी * अपेक्षित * होने की संभावना है, यानी यह कुंजी के लिए एक बग है, वहां नहीं होना चाहिए, फिर अपवाद फेंकना असफलता का सही दृष्टिकोण है। अन्यथा, आपको उस स्थिति का पता लगाना चाहिए * बिना किसी अपवाद का उपयोग करना - अपवादों के साथ गैर असाधारण मामलों को संभालना एक बुरा विचार है, आईएमओ। –

+0

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

0

यदि आप जानते हैं कि आमतौर पर शब्दकोश में कुंजी होती है, तो आपको इसे एक्सेस करने से पहले इसकी जांच करने की आवश्यकता नहीं है।

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

0

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

सीधा lock धारावाहिक सभी पढ़ने की पहुंच जो संभवतः पढ़ने के लिए वांछित नहीं हो सकता है और लिखने अपेक्षाकृत कम हैं। उस स्थिति में ReaderWriterLockSlim का उपयोग करना बेहतर हो सकता है। नकारात्मकता यह है कि कोड थोड़ा अधिक जटिल है और लिखना थोड़ा धीमा है।

1

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

1

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

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

बेशक, कभी-कभी यह मजेदार सामान ही होता है।

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

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