c# - अनुपलब्ध कोड, लेकिन एक अपवाद के साथ पहुंच योग्य




exception unreachable-code (6)

यह कोड एक एप्लिकेशन का हिस्सा है जो ODBC कनेक्टेड डेटाबेस से पढ़ता है और लिखता है। यह डेटाबेस में एक रिकॉर्ड बनाता है और फिर जांचता है कि क्या कोई रिकॉर्ड सफलतापूर्वक बनाया गया है, तो true वापस आ रहा true

नियंत्रण प्रवाह की मेरी समझ इस प्रकार है:

जब एक विधि कॉल वस्तु की वर्तमान स्थिति के लिए अमान्य हो "तो command.ExecuteNonQuery() Invalid​Operation​Exception को फेंकने के लिए प्रलेखित है। इसलिए, यदि ऐसा होता है, तो try ब्लॉक का निष्पादन बंद हो जाएगा, finally ब्लॉक निष्पादित किया जाएगा, फिर return false; को निष्पादित करेगा return false; तल पर।

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

private static bool createRecord(String table,
                                 IDictionary<String,String> data,
                                 System.Data.IDbConnection conn,
                                 OdbcTransaction trans) {

    [... some other code ...]

    int returnValue = 0;
    try {
        command.CommandText = sb.ToString();
        returnValue = command.ExecuteNonQuery();

        return returnValue == 1;
    } finally {
        command.Dispose();
    }

    return false;
}

यहाँ समझने में मेरी क्या त्रुटि है?


अंत में ब्लॉक निष्पादित किया जाएगा, फिर झूठे को निष्पादित करेगा; तल पर।

गलत। finally में अपवाद निगल नहीं है। यह इसका सम्मान करता है और अपवाद को सामान्य रूप में फेंक दिया जाएगा। यह ब्लॉक को समाप्त होने से पहले (अंत में या बिना किसी अपवाद के) कोड को अंजाम देगा।

यदि आप अपवाद को निगल जाना चाहते हैं, तो आपको catch ब्लॉक का उपयोग करना चाहिए जिसमें कोई throw न हो।


अंतिम कथन return false है, अनुपलब्ध है, क्योंकि ट्राई ब्लॉक एक catch भाग को याद कर रहा है जो अपवाद को हैंडल करेगा, इसलिए finally ब्लॉक के बाद अपवाद को फिर से हटा दिया गया है और निष्पादन कभी भी अंतिम विवरण तक नहीं पहुंचता है।


आपके पास catch ब्लॉक नहीं है, इसलिए अपवाद अभी भी फेंका गया है, जो रिटर्न को ब्लॉक करता है।

अंत में ब्लॉक निष्पादित किया जाएगा, फिर झूठे को निष्पादित करेगा; तल पर।

यह गलत है, क्योंकि अंत में ब्लॉक निष्पादित किया जाएगा, और फिर एक अनकहा अपवाद होगा।

finally ब्लॉक का उपयोग सफाई के लिए किया जाता है, और वे अपवाद को नहीं पकड़ते हैं। अपवाद को वापसी से पहले फेंक दिया जाता है, इसलिए, वापसी कभी नहीं होगी, क्योंकि अपवाद को पहले फेंक दिया गया है।

आपका आईडीई सही है कि यह कभी नहीं पहुंचेगा, क्योंकि अपवाद को फेंक दिया जाएगा। केवल catch ब्लॉक अपवादों को पकड़ने में सक्षम हैं।

docs.microsoft.com/en-us/dotnet/csharp/language-reference/… से पढ़ना,

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

यह स्पष्ट रूप से दिखाता है कि अंत में अपवाद को पकड़ने का इरादा नहीं है, और यदि आप finally बयान से पहले एक खाली catch स्टेटमेंट catch , तो आप सही होंगे।


आपके पास अपने कोड में दो वापसी पथ हैं, जिनमें से दूसरा पहले की वजह से पहुंच से बाहर है। आपकी try ब्लॉक return returnValue == 1; में अंतिम विवरण return returnValue == 1; आपकी सामान्य वापसी प्रदान करता है, इसलिए आप कभी भी return false; तक नहीं पहुँच सकते return false; विधि ब्लॉक के अंत में।

एफडब्ल्यूआईडब्ल्यू, finally ब्लॉक से संबंधित छूट का आदेश है: कोशिश ब्लॉक में रिटर्न वैल्यू की आपूर्ति करने वाले अभिव्यक्ति का पहले मूल्यांकन किया जाएगा, फिर अंत में ब्लॉक को निष्पादित किया जाएगा, और फिर गणना किए गए एक्सप्रेशन मूल्य को वापस किया जाएगा (कोशिश ब्लॉक के अंदर) ।

अपवाद पर प्रवाह के बारे में ... एक catch बिना, finally अपवाद से पहले निष्पादित किया जाएगा, फिर अपवाद को विधि से बाहर निकाल दिया जाएगा; कोई "वापसी" पथ नहीं है।


चेतावनी इसलिए है क्योंकि आपने catch उपयोग नहीं किया है और आपकी विधि मूल रूप से इस तरह लिखी गई है:

bool SomeMethod()
{
    return true;
    return false; // CS0162 Unreachable code detected
}

चूंकि आप finally उपयोग करने के लिए पूरी तरह से उपयोग using हैं, इसलिए पसंदीदा समाधान पैटर्न का using है:

using(var command = new WhateverCommand())
{
     ...
}

यह पर्याप्त है, यह सुनिश्चित करने के लिए कि Dispose को क्या कहा जाएगा। यह कोड ब्लॉक के सफल निष्पादन के बाद या (पहले) कॉल स्टैक में कुछ catch (पैरेंट कॉल डाउन, राइट?) के सफल निष्पादन के बाद कहा जाता है।

यदि यह निपटान के बारे में नहीं होगा, तो

try { ...; return true; } // only one return
finally { ... }

पर्याप्त है, क्योंकि आपको विधि के अंत में कभी भी false नहीं लौटना होगा (उस पंक्ति की कोई आवश्यकता नहीं है)। आपका तरीका या तो कमांड निष्पादन ( true या false ) का परिणाम true या अन्यथा एक अपवाद को फेंक देगा।

अपेक्षित अपवादों को लपेटकर स्वयं अपवादों को फेंकने पर विचार करें ( InvalidOperationException constructor देखें ):

try { ... }
catch(SomeExpectedException e)
{
    throw new SomeBetterExceptionWithExplanaition("...", e);
}

यह आमतौर पर नेस्टेड कॉल अपवाद की तुलना में कॉलर को कुछ अधिक सार्थक (उपयोगी) कहने के लिए उपयोग किया जाता है।

ज्यादातर बार आप वास्तव में बिना किसी अपवाद के परवाह नहीं करते हैं। कभी-कभी आपको यह सुनिश्चित करने की आवश्यकता होती है कि finally अपवाद कहे जाने पर भी इसे कहा जाए। इस मामले में आप बस इसे स्वयं पकड़ लेते हैं और फिर से फेंक देते हैं ( इस उत्तर को देखें):

try { ... }
catch { ...; throw; } // re-throw
finally { ... }

जब अपवाद को फेंक दिया जाता है, तो स्टैक कम हो जाएगा (निष्पादन फ़ंक्शन से बाहर निकल जाएगा) एक मान लौटाए बिना, और फ़ंक्शन के ऊपर स्टैक फ़्रेम में कोई भी पकड़ ब्लॉक इसके बजाय अपवाद को पकड़ लेगा।

इसलिए, return false कभी निष्पादित नहीं होगी।

नियंत्रण प्रवाह को समझने के लिए अपवाद को मैन्युअल रूप से फेंकने का प्रयास करें:

try {
    command.CommandText = sb.ToString();
    returnValue = command.ExecuteNonQuery();

    // Try this.
    throw new Exception("See where this goes.");

    return returnValue == 1;
} finally {
    command.Dispose();
}






unreachable-code