2009-09-21 25 views
5

.NET प्रोग्रामिंग दिशानिर्देश बताते हैं कि हमें सामान्य अपवाद नहीं लेना चाहिए। मुझे लगता है निम्नलिखित कोड सामान्य अपवाद प्रकार पकड़ की वजह से बहुत अच्छा नहीं है:.NET कैच सामान्य अपवाद

private object CreateObject(string classname) 
    { 
     object obj = null; 
     if (!string.IsNullOrEmpty(classname)) 
     { 
      try 
      { 
       System.Type oType = System.Type.GetTypeFromProgID(customClass); 
       obj = System.Activator.CreateInstance(oType); 
      } 
      catch (Exception ex) 
      { 
       Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message); 
      } 
     } 
     return obj; 
    } 

निम्न कोड में मैं विशेष रूप से अपवाद नहीं लेकिन उन सभी को और उसके बाद मैं अपवाद फिर से फेंक को पकड़ने के मामले में से अलग है गैर-सामान्य अपवाद। हालांकि "CreateInstance" फ़ंक्शन कई अपवादों को फेंक सकता है (ArgumentNullException, ArgumentException, NotSupportedException, TargetInvocationException, MethodAccessException, MemberAccessException, InvalidComObjectException, MissingMethodException, COMException, TypeLoadException)।

क्या यह अन्य सभी व्यक्तिगत अपवादों को पकड़ने के लिए स्वीकार्य है? या कोई बेहतर तरीका है?

private object CreateObject(string classname) 
    { 
     object obj = null; 
     if (!string.IsNullOrEmpty(classname)) 
     { 
      try 
      { 
       System.Type oType = System.Type.GetTypeFromProgID(customClass); 
       obj = System.Activator.CreateInstance(oType); 
      } 
      catch (NotSupportedException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (TargetInvocationException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (COMException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (TypeLoadException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (InvalidComObjectException ex) 
      { 
       Log.Error("...." + ex.Message); 
      } 
      catch (Exception ex) 
      { 
       Log.Error("Unable to create instance for COM Object with class name " + classname + "\n" + ex.Message); 
       throw; 
      } 
     } 
     return obj; 
    } 
+0

डुप्लिकेट: http://stackoverflow.com/questions/204814/is-there-any-valid-reason-to-ever-ignore-a-caught-exception –

उत्तर

9

फ्रेमवर्क के .NET 2+ में सामान्य अपवादों को पकड़ना काफी स्वीकार्य है।

- संपादित करें

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

+3

मैं सहमत हूं। कभी-कभी मुझे लगता है कि हम इसे चरम सीमाओं के सामान्य अपवाद को नहीं पकड़ते हैं। –

+5

मैं असहमत हूं। यह आपके आवेदन को असाधारण स्थिति में छोड़ देगा। आपको केवल उन अपवादों को संभालना चाहिए जिन्हें आप कुछ कर सकते हैं। बस लॉगिंग और आगे बढ़ना एक बुरा विचार है। –

+0

@ justin.m.chase: यह एक बहुत ही अजीब स्थिति है। इसलिए, जब भी आपका ऐप क्रैश हो जाता है, तो आप अपने उपयोगकर्ताओं को अपने बजाय .NET सामान्य त्रुटि पृष्ठ देखना पसंद करेंगे? –

1

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

जब तक आप अपवादों को निगलते नहीं हैं, लेकिन उन्हें लॉग इन करें और पृष्ठभूमि में उचित रूप से उन पर प्रतिक्रिया दें।

1

यदि आप किसी भिन्न प्रकार के अपवाद के साथ कुछ विशेष करना चाहते हैं तो इसे एक अलग पकड़ ब्लॉक में पकड़ें। अन्यथा उन्हें अलग से लॉग इन करना व्यर्थ है।

1

वहाँ एक कठोर नियम है कि हम सामान्य अपवाद लेकिन दिशानिर्देश उपयोग नहीं करना चाहिए नहीं है कहते हैं

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

और कभी-कभी आपके एप्लिकेशन में कोई अपवाद होता है विशिष्ट अपवाद हैंडलिंग के कारण कोड में संभाला गया तो आपका एप्लिकेशन क्रैश के लिए जा सकता है ..

तो बेहतर दृष्टिकोण सभी विशिष्ट अपवाद को संभालने और फिर सामान्य अपवाद भी इतना है कि आवेदन दुर्घटना के बिना स्थिर रहने के लिए एक कोने देना है ..

और उन अवांछित सामान्य अपवाद सूचना या आवेदन के भविष्य के संस्करण में सुधार के लिए कहीं न कहीं लॉग इन किया जा सकता है ..

11

एक सामान्य नियम के रूप में आप अपवाद जब तक पकड़ नहीं करना चाहिए:

  1. आप एक विशिष्ट अपवाद है कि आप को संभाल और बारे में कुछ कर सकते हैं। हालांकि इस मामले में आपको हमेशा यह जांचना चाहिए कि आपको पहले स्थान पर अपवाद से बचने और उससे बचने की कोशिश नहीं करनी चाहिए।

  2. आप किसी एप्लिकेशन के शीर्ष स्तर पर हैं (उदाहरण के लिए यूआई) और उपयोगकर्ता को डिफ़ॉल्ट व्यवहार प्रस्तुत नहीं करना चाहते हैं। उदाहरण के लिए आप "कृपया हमें अपने लॉग भेजें" शैली संदेश के साथ एक त्रुटि संवाद चाहते हैं।

  3. किसी भी तरह से निपटने के बाद आप अपवाद को फिर से फेंक देते हैं, उदाहरण के लिए यदि आप डीबी लेनदेन वापस लेते हैं।

इस उदाहरण में आप इन सभी विभिन्न प्रकारों को क्यों पकड़ रहे हैं? मुझे ऐसा लगता है कि अपने कोड अभी हो सकता है:

try 
{ 
    System.Type oType = System.Type.GetTypeFromProgID(customClass); 
    return System.Activator.CreateInstance(oType); 
} 
catch (Exception ex) 
{ 
    Log.Error("...." + ex.Message); 

    //the generic catch is always fine if you then do this: 
    throw; 
} 

तो आपकी समस्या को शासन का एक उदाहरण है (3) - आप एक अपवाद प्रवेश करना चाहते हैं, लेकिन फिर जारी रखने के लिए और ऊपर उस पर फेंक देते हैं।

सभी विभिन्न प्रकार हैं वहाँ इतना है कि कुछ मामलों आप जानते हैं कि आप को संभाल सकता है (यानी मामला 1) में। उदाहरण के लिए मान लीजिए कि आप जानते हैं कि एक अप्रबंधित कॉल कि चारों ओर COMException काम करता है कि वहाँ - फिर अपना कोड हो जाता है:

try 
{ 
    System.Type oType = System.Type.GetTypeFromProgID(customClass); 
    return System.Activator.CreateInstance(oType); 
} 
catch (COMException cex) 
{ //deal with special case: 
    return LoadUnmanaged(); 
} 
catch (Exception ex) 
{ 
    Log.Error("...." + ex.Message); 

    //the generic catch is always fine if you then do this: 
    throw; 
} 
+0

मैं इन सभी अलग-अलग प्रकार के अपवादों को पकड़ता हूं क्योंकि वे हो सकते हैं (उदाहरण के लिए उपयोग एक ऐसे वर्ग का नाम पारित कर सकता है जो समर्थित नहीं है या ठीक से पंजीकृत नहीं है) और उस स्थिति में अपवाद के लिए अग्रिम में जांच करने का कोई अच्छा तरीका नहीं है (जैसा कि मैं ArgumentNullException के लिए जाँच कर सकते हैं)। – Ioannis

+0

मुझे यकीन है कि वे सभी हो सकते हैं, लेकिन जब तक कि आप उस अपवाद प्रकार के लिए कुछ विशिष्ट नहीं करने जा रहे हैं, तो आप सामान्य 'अपवाद' को पकड़ने और उसे ऊपर फेंकने से बेहतर होते हैं। – Keith

+1

यह उत्तर बिल्कुल सही है। कुंजी यह है कि आप उन्हें ऊपर निगलने के लिए सामान्य अपवाद फेंक रहे हैं। –

1

यह है क्योंकि यह एक संभावित पता चलता है, गरीब अभ्यास माना जाता है आदतन आधार Exception को पकड़ने के लिए जब से निपटने त्रुटियों के साथ काम वास्तव में आप क्या कर रहे हैं के रूप में समझने की कमी। जब आप कोड पकड़ Exception यह क्या पढ़ता है के एक ब्लॉक देखते हैं, है, जहां कि कुछ भी एक NullReferenceException से एक OutOfMemoryException तक होती सकता है "कुछ भी यहाँ गलत हो जाता है, ऐसा करने के"।

ही सभी त्रुटियों के उपचार में खतरे से, इसका अर्थ है आप कैसे गंभीर त्रुटि हो या आप कैसे त्रुटि को हल करने के बारे में जाना हो सकता है हो सकता है के बारे में परवाह नहीं है। 99% समय, जब मैं catch(Exception ex) कोड देखता हूं, तो तुरंत उस कोड के बाद होता है जो अपवाद को निगलता है, वास्तव में बयान विफल क्यों नहीं होता है। ओह।

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

1

मैं कीथ के उत्तर से सहमत हूं। कोड उदाहरण दोनों के साथ असली मुद्दा यह है कि वे शून्य वापस कर सकते हैं। आपके पास CreateObject नामक एक विधि है जो प्रकार ऑब्जेक्ट का एक उदाहरण देता है। यह विधि किसी कारण से विफल रही, जैसे कि COMException। दोनों कोड उदाहरण तब शून्य हो जाएंगे। कॉलिंग कोड अब परिणाम बनाम नल की जांच के लिए ज़िम्मेदार है, या यह एक NullReferenceException फेंक देगा।

Framework Design Guidelines 2nd ed. का हवाला देते हुए:

एक सदस्य सफलतापूर्वक क्या यह करने के लिए डिज़ाइन किया गया है नहीं कर सकते हैं, तो यह एक निष्पादन विफलता, विचार किया जाना चाहिए और एक अपवाद फेंका जाना चाहिए।

ऐसा नहीं किया गया जो इसका नाम सुझाता है। फेंकना!

कीथ के कोड ठीक है; अपवाद लॉग और ठीक करने के लिए ठीक है।

यह एक निजी विधि है, इसलिए यकीनन डिज़ाइन दिशानिर्देशों लागू नहीं है। मैं अभी भी उन्हें यहां लागू कर दूंगा, हालांकि - जब आप अपवाद हैंडलिंग का उपयोग कर सकते हैं तो "अगर (परिणाम == शून्य)" के साथ अपना कोड कूड़े क्यों करें?

+0

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

+0

@supercat: यदि हम अन्य डेवलपर्स पर भरोसा कर सकता है (और खुद) हमेशा की जांच करने के लिए यदि दिए गए मान रिक्त है ... – TrueWill

+0

पर विचार है कि यह असफल हो सकता है बिना एक समारोह TryGetFoo कहा जाता है को कॉल करते हैं कौन सा ठीक होगा, वे वे क्या मिल के पात्र हैं। वे एमएस-पैटर्न "TryGetFoo" विधि से वापसी मूल्य (सफलता/विफलता ध्वज) को और भी आसानी से अनदेखा कर सकते हैं। MS-पैटर्न संस्करण कुछ स्थितियों जो हो सकता है या तो एक अच्छा या बुरा बात में एक सुविधा है: यह संभव है एक समारोह में एक अपवाद फेंक के लिए, लेकिन अभी भी सेट पारित कर दिया वैरिएबल कुछ करने के लिए इससे पहले कि यह ऐसा नहीं करता है। यह अच्छा हो सकता है यदि चर एक आईडीस्पोज़ेबल है, लेकिन अगर भ्रम विधि के रिटर्न कोड को अनदेखा किया जाता है तो भ्रम पैदा हो सकता है। – supercat

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