2010-07-12 20 views
6

के साथ कुछ बड़े पैमाने पर भारी समस्या में गिर गया है, हाल ही में मैं एक ऐसे सॉफ्टवेयर का विकास कर रहा हूं जो किसी वेबसाइट से XML जानकारी को पार्स और प्रदर्शित करता है। काफी सही है?मुझे लगता है कि NullReferenceExceptions

मुझे NullReferenceExceptions के लोड मिल रहे हैं। उदाहरण के लिए, इस विधि:

private void SetUserFriends(List<Friend> list) 
{ 
    int x = 40; 
    int y = 3; 

    if (list != null) 
    { 
     foreach (Friend friend in list) 
     { 
      FriendControl control = new FriendControl(); 
      control.ID = friend.ID; 
      control.URL = friend.URL; 
      control.SetID(friend.ID); 
      control.SetName(friend.Name); 
      control.SetImage(friend.Photo); 

      control.Location = new Point(x, y); 
      panel2.Controls.Add(control); 

      y = y + control.Height + 4; 
     } 
    } 
} 

मैं था एक बदसूरत पाप के रूप में, तो वास्तविक foreach पाश के आसपास आदेश एक अपवाद को रोकने के लिए रैप करने के लिए।

मुझे लगता है कि मैं वास्तव में समस्या को ठीक करने के बजाय एक फ्लैट टायर पर बांदाइड्स डाल रहा हूं। क्या इस समस्या से निपटने का कोई तरीका है? हो सकता है कि एक प्रोग्राम मुझे प्रोग्रामिंग पैटर्न के बारे में पढ़ा जाए या क्या नहीं?

वास्तव में, मैं खो गया हूं। मैं शायद गलत सवाल पूछ रहा हूँ।

+8

आपको उस कोड को देखना चाहिए जो * कॉलिंग * 'SetUserFriends' है। यदि आप मानते हैं कि दोस्तों की सूची 'शून्य' नहीं होनी चाहिए (जो एक उचित पर्याप्त धारणा है, तो मैं कहूंगा), तो बग जो कुछ भी * गुजर रहा है * में है। जब आप अपवाद प्राप्त करते हैं तो कॉल स्टैक को देखने के लिए डीबगर का उपयोग करें। –

+1

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

+3

यह एक साइड नोट है, लेकिन मैं IENumerable को स्वीकार करने के लिए बहस करता हूं, ताकि विधि को कॉलर को किसी विशेष संग्रह वर्ग का उपयोग करने की आवश्यकता न हो। –

उत्तर

15

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

if (list == null) 
{ 
    throw new ArgumentNullException(list); 
} 

यह एक आम रक्षात्मक प्रोग्रामिंग पैटर्न है - यह सुनिश्चित करने के लिए जांचें कि आपके द्वारा प्रदान किया गया डेटा मूल स्वच्छता जांच पास करता है।

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

+0

+1 यदि आप लगातार यह करते हैं, तो आप दर्द से सीखेंगे कि कोड को कैसे लिखना है जो अनजाने नल से बचाता है। रक्षात्मक प्रोग्रामिंग –

+1

+1 हालांकि, इस परिदृश्य के लिए शून्य सहकर्मी सुझाव थोड़ा हास्यास्पद है। –

4

मैं शायद "कोई एकाधिक बाहर निकलें" भीड़ द्वारा downvoted करने के लिए जा रहा हूँ, लेकिन मैं आम तौर पर सही विधि की शुरुआत में एक सरल चेक के साथ कि संभाल:

if (list == null || list.Count == 0) return; 

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

लेकिन मैं कोडेका से सहमत हूं, इसमें आपको कॉलिंग कोड देखने और बाहर निकलने की आवश्यकता है यदि आप इसे वहां से सुधार सकते हैं।

+4

यह दृष्टिकोण * शायद * इस विशिष्ट मामले के लिए काम कर सकता है, लेकिन सामान्य रूप से यह बहुत सूक्ष्म बग की ओर जाता है। अधिकांश समय हम उचित रूप से अनुमान लगा सकते हैं कि कॉलर का उद्देश्य 'शून्य' में गुज़रने के इरादे से नहीं है, इसलिए अपवाद के साथ निरस्त होना सुरक्षित है। –

+2

यह दस्तावेज किया जाना चाहिए कि कोई विधि शून्य को स्वीकार करती है या नहीं (और आदर्श रूप में) यदि यह पूर्व शर्त पूरी नहीं होती है तो यह क्या करता है। मैं @Rex से सहमत हूं कि चुप रिटर्न अक्सर डिबगिंग को चोट पहुंचा सकता है। –

+0

मैं आप दोनों से पूरी तरह से सहमत हूं, लेकिन ऐसे मामले हैं जहां यह उपयोगी हो सकता है –

0

अमान्य इनपुट दिए जाने पर मैं जल्दी वापस आऊंगा (या अमान्य अर्ग्यूमेंट अपवाद को फेंक दूंगा)।

उदाहरण के लिए:

private void SetUserFriends(List<Friend> list) 
{ 
    if (list == null) 
     return; 

    /* Do stuff */ 
} 

वैकल्पिक रूप से आप सामान्य अशक्त वालों पैटर्न का उपयोग कर सकते हैं:

private void SetUserFriends(List<Friend> list) 
{ 
    list = list ?? new List<Friend>(); 

    /* Do Stuff */ 
} 
+1

के लिए –

+1

जल्दी लौटने और फेंकने * बेहद अलग दृष्टिकोण हैं। आप किसकी सिफारिश करते हैं? –

+0

उहम, यदि आप अपवाद फेंकने जा रहे हैं, तो सही व्यक्ति 'ArgumentNullException' होगा, जैसा कि माइकल के उदाहरण से पता चला है। –

1

साथ ही ArgumentNullException अपवाद फेंक वहाँ भी कुछ "अशक्त Obejct पैटर्न" कहा जाता है जो आप कर सकते हैं अगर आप चाहते हैं, तो शून्य के लिए गुजरने के लिए, उदाहरण के लिए, कुछ मौजूद नहीं है, लेकिन स्पष्ट रूप से नल की जांच नहीं करना चाहते हैं। अनिवार्य रूप से यह एक स्टब क्लास है जो एक ही इंटरफ़ेस को लागू करता है, लेकिन इसकी विधियां आमतौर पर खाली होती हैं या उन्हें पूर्ण करने के लिए पर्याप्त होती हैं। http://en.wikipedia.org/wiki/Null_Object_pattern

मूल्य प्रकारों के लिए भी उपयोगी है जो आसानी से अपने अस्तित्व को व्यक्त नहीं कर सकते हैं, शून्य होने में सक्षम नहीं होने के कारण।

+0

दिलचस्प है, लेकिन मुझे यकीन नहीं है कि यह यहां लागू होता है, क्योंकि शून्य ऑब्जेक्ट पैटर्न की सबसे नज़दीकी चीज़ यहां एक खाली सूची रखेगी। दूसरी समस्या, जिसे मैंने कहीं और बताया है, यह है कि इस विधि को शायद सूची के बजाय एक आईनेमरेबल स्वीकार करना चाहिए। –

+0

सच है, लेकिन उन्होंने उल्लेख किया कि यह उनके "नल रेफरेंस अपवादों के लोड" का केवल एक उदाहरण है। यह उनके कुछ अन्य लोगों के लिए सही समाधान हो सकता है। इसके लिए मैं अपवाद भी फेंक दूंगा। – Spike

+0

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

2

ऐसा लगता है कि रक्षात्मक प्रोग्रामिंग और पैरामीटर सत्यापन वह है जिसे आप ढूंढ रहे हैं।

के रूप में अन्य लोगों ने कहा, साधारण पैरामीटर मान्यता आप के लिए काम करेंगे:

if (list == null) 
    throw new ArgumentNullException("list"); 

वैकल्पिक रूप से, अगर आप लगातार प्रत्येक पैरामीटर के लिए इस तरह के चेक लिखने के टायर, तुम बाहर कई खुला स्रोत में से एक की जांच कर सकता है। नेट पूर्व शर्त प्रवर्तन पुस्तकालयों। मुझे CuttingEdge.Conditions का शौक है।

इस तरह, आप कुछ इस तरह का उपयोग कर सकते हैं:

Condition.Requires(list, "list").IsNotNull(); 

हालांकि, दोनों में से किसी की तरह एक पूर्व शर्त की स्थापना से ऊपर सिर्फ निर्दिष्ट करेगा कि आपके विधि nulls स्वीकार नहीं करता। आपकी समस्या अभी भी मौजूद है कि आप विधि में नल पास कर रहे हैं! इसे ठीक करने के लिए, आपको यह जांचना होगा कि आपके तरीकों को क्या बुला रहा है, और काम कर रहा है कि क्यों नल ऑब्जेक्ट्स पास किए जा रहे हैं।

+0

+1 पर स्टैक ट्रेस का पालन करना आसान हो जाता है। –

+1

और CuttingEdge.Conditions संदर्भित करने के लिए +1 ;-) – Steven

0

आप वास्तव में गलत सवाल पूछ रहे हैं। सही सवाल यह है कि "शून्य एक अमान्य इनपुट या ध्वज का प्रतिनिधित्व करता है जिसका अर्थ है एक्स"।

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

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