जानबूझकर अपवादों को पकड़ने का उपयोग करना


10

if...elseअपवाद हैंडलिंग के साथ लिपटे एक ठेठ के लिए , कोड अनुलिपि से बचने के लिए निम्न उदाहरण एक अनुशंसित अभ्यास है?

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        throw new Exception();
    }
catch(Exception ex)
{
    return null;
}

के बजाय...

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        return null;
    }
}
catch(Exception ex)
{
    return null;
}

मुझे पता है कि एक मामूली प्रदर्शन हिट है, लेकिन मैं सोच रहा हूं कि क्या यह एक स्वीकार्य अभ्यास माना जाता है। मैं वर्तमान में इसे दूसरी विधि करता हूं - विशेष रूप से ऐसे मामलों में जहां मुझे विशिष्ट अपवादों को अलग ढंग से संभालने की आवश्यकता है - लेकिन मैं सोच रहा था कि क्या पहली विधि सरल मामलों के लिए उपयुक्त है।


अगर विधि काफी छोटी है, तो मैं अभी और हटा दूंगा और ट्राईकैच ब्लॉक के बाहर नल लौटाऊंगा, इसलिए मुझे केवल एक बार नल वापस करना होगा।
फैबियो मारकोलिनी

जवाबों:


12

Microsoft द्वारा प्रवाह नियंत्रण के लिए अपवाद हैंडलिंग का उपयोग करना हतोत्साहित करता है।

और विषय पर एक गोल मेज उपलब्ध है।

यह कहा जा रहा है, C # ऐसा करने का समर्थन करता है, और मुझे लगता है कि यह उस स्थिति पर निर्भर करता है, जो अपवाद के लिए सबसे उपयुक्त प्रतिक्रिया है।


1
यह मुझ पर प्रहार करता है कि इस तरह की बात घटनाओं का उपयोग न करने के लिए वास्तविक कोशिश कर रही है।
राडारबॉब

@ श्रंगार: इस से संबंधित घटनाएं कैसे होती हैं?

@grovesNL - कैच ब्लॉक में एक निश्चित विधि को कॉल करने के लिए एक विशिष्ट बिंदु पर एक अपवाद को फेंकना? मेरे लिए एक घटना की तरह है।
राडारबॉब

@ शरदबोब: यह एक घटना नहीं है। उत्तर के राउंडटेबल लिंक में चर्चा किए जाने के साथ बहुत सारे नमूना उपयोग के मामले हैं, जहां इसका उपयोग किया जाएगा।

1
@radarbob केवल स्पष्टीकरण का एक सा, अपवाद कॉलर को संकेत देने के एक तरीके के रूप में डिज़ाइन किया गया था कि कुछ ऐसा हुआ है जिसे कॉल करने की विधि को संभालने में असमर्थ है। हालांकि, एक घटना के लिए सुनना चाहिए। एक अपवाद एक कार्यक्रम के सामान्य प्रवाह का एक मजबूर रुकावट है। एक अनकहा अपवाद पूरे एप्लिकेशन को रोक देगा।

6

प्रदर्शन हिट शायद सबसे नगण्य है, जैसा कि इस उत्तर में बताया गया है ।

तो आइए इस विचार के साथ जाएं कि प्रदर्शन कोई समस्या नहीं है। आप फेंक रहे हैं System.Exception, बस catchखंड में निष्पादन को स्थानांतरित करने के लिएBadControlFlowThatShouldBeRewrittenExceptionहालांकि फेंकना शायद ओवरकिल होगा।

चलिए इसे तोड़ते हैं। हमारे पास है:

  • विधि GetDataFromServer(विधि नाम C # में PascalCase होना चाहिए), जो संभवतः एक अपवाद फेंक सकता है, या वापस कर सकता है bool
  • यदि परिणाम होता true, तो दौड़ते ProcessData
  • nullअन्यथा वापस लौटें ।

ऐसा लगता है कि यह कोड जिस पद्धति से लिखा गया है, वह बहुत अधिक काम कर रहा है। GetDataFromServerएक लौटने boolएक डिजाइन दोष की तरह दिखता है, मैं करने के लिए है कि विधि की उम्मीद होगी डेटा यह सर्वर से हो रही है वापसी , कुछ IEnumerable<SomeType>यानी खुश पथ रिटर्न - कि 0 या अधिक आइटम होते हैं n आइटम जहां n> 0 , नहीं-तो-खुश पथ 0 आइटम लौटाता है, और दुखी पथ एक अखंड अपवाद के साथ उड़ता है, जो कुछ भी है।

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

try
{
    var result = GetDataFromServer();
    return ProcessData(result);
}
catch
{
    return null;
}

यहां आप ProcessDataदेखेंगे और देखेंगे कि यह पुनरावृत्ति कर रहा है result, और nullयदि कोई आइटम नहीं है तो वापस लौटता है IEnumerable

अब विधि क्यों लौट रही है null? सर्वर डाउन था? क्या क्वेरी में कोई बग है? कनेक्शन स्ट्रिंग गलत क्रेडेंशियल्स का उपयोग कर रहा है? जब भी GetDataFromServerआप एक अपवाद के साथ उड़ते हैं, जिसकी आप अपेक्षा नहीं कर रहे हैं, तो आप इसे निगल रहे हैं, इसे कालीन के नीचे हिलाते हुए और एक nullमूल्य लौटाते हैं । मैं इस मामले में विशिष्ट अपवादों को पकड़ने की सलाह देता हूं, और बाकी सब कुछ लॉग करता हूं; डिबगिंग उस तरह से बहुत आसान हो जाएगा।

एक सामान्य catchक्लॉज के साथ जो अपवाद पर कब्जा नहीं करता है, किसी भी चीज का निदान करना काफी कठिन हो जाता है। मैं इसके बजाय न्यूनतम रूप से ऐसा करूंगा:

catch(Exception e)
{
    return null;
}

अब आप कम से कम टूट सकते हैं और निरीक्षण कर सकते हैं eकि क्या चीजें गलत हैं।


TL; DR : नहीं, प्रवाह नियंत्रण के लिए अपवादों को फेंकना और पकड़ना अच्छा विचार नहीं है।


यह उत्तर दर्शाता है कि मैंने अपने कोड को सामान्य रखने की कोशिश क्यों की: मैं हर एक अपवाद को सूचीबद्ध नहीं करना चाहता था जिसे मैं वास्तव में अपने कोड में बनाता हूं; मैं वास्तविक विधि नामों को सूचीबद्ध नहीं करना चाहता था; मैं विधि घोषणा को सूचीबद्ध नहीं करना चाहता था; मैं वाक्यविन्यास सुझाव नहीं चाहता था। मेरे पास एक ही सवाल था कि क्या प्रवाह नियंत्रण के अपवादों को फेंकना ठीक था, जो कि बी 2 के द्वारा तुरंत उत्तर दिया गया था। मुझे मेटा पर इस पर बहस करने में खुशी होगी।

3
तब लगता है कि प्रोग्रामर के लिए एक सवाल होना चाहिए था। हम कोड की समीक्षा करते हैं, विचारों की नहीं।
मलाची

2

आपके पहले उत्तर में एक प्रदर्शन हिट है जिसे वहां होने की आवश्यकता नहीं है।

try
{
    if (GetDataFromServer())
    {
        return ProcessData();
    }
    else
    {
        throw new Exception();
    }
catch(Exception ex)
{
    return null;
}

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

यदि आप return null; इसे दूसरे स्टेटमेंट में करना चाहते हैं तो उस कैच में नहीं जिसे दूसरे स्टेटमेंट से फेंके जाने के बाद पकड़ा जाता है।

संभवतः आपके वास्तविक कोड पर लागू नहीं होता है , लेकिन जेनेरिक कोड के लिए जो आपने दिया था वह लागू होता है।

मानकों का कहना है कि आपको ऐसा नहीं करना चाहिए।

मानकों का कहना है कि आपको इसे इस तरह से करना चाहिए, (फिर से ओपी में जेनेरिक कोड के आधार पर)

if (GetDataFromServer())
{
    return ProcessData();
}
else
{
    Return null
}

और चूँकि आपके पास कोई विशिष्ट अपवाद नहीं है, जिसे आप पकड़ रहे हैं, यहाँ भी आपको पकड़ने की कोशिश नहीं करनी चाहिए।

जब वे अपवाद होते हैं, तो आप अपवाद देखना चाहते हैं ताकि आप उस समस्या को ठीक कर सकें जो अपवाद बनाता है।


1

क्यों नहीं आसान है:

if (!GetDataFromServer()) return null;
ProcessData();

यदि एक अपवाद हैंडलर मौजूद होने जा रहा है तो यह प्रोसेसडाटा () में होना चाहिए


मैं ProcessData()ऊपरवाले के स्तर से अपवादों को पारित क्यों नहीं करना चाहता ?
ग्रूव्सएनएल

@grovesNL यहां अपवाद के साथ उपयोगी नहीं था।
लोरेन Pechtel

1
ऐसा कैसे? यदि ProcessData()एक अपवाद फेंकता है तो अब इसे संभाला नहीं जाता है। मैं इसे return nullइस स्तर पर चाहता हूं अगर खुद ProcessData()को संशोधित किए बिना एक अपवाद फेंकता ProcessData()है।
ग्रूव्सएनएल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.