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




exception unreachable-code (8)

यह कोड एक एप्लिकेशन का हिस्सा है जो 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;
}

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


चेतावनी इसलिए है क्योंकि आपने 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 { ... }

संकलक चेतावनी (स्तर 2) CS0162

पता नहीं लगने वाला कोड

संकलक ने कोड का पता लगाया जो कभी भी निष्पादित नहीं किया जाएगा।

जो बस कह रहा है, कंपाइलर स्टैटिक एनालिसिस के माध्यम से पर्याप्त समझता है कि इसे कैंट तक नहीं पहुंचाया जा सकता और इसे पूरी तरह से संकलित IL से छोड़ दिया जाता है (इसलिए आपकी चेतावनी)

नोट : आप डीबगर के साथ अनुपलब्ध कोड पर कदम रखने की कोशिश करके या एक IL एक्सप्लोरर का उपयोग करके अपने स्वयं के लिए इस तथ्य को साबित कर सकते हैं

finally एक अपवाद पर चल सकता है, (हालांकि वह अलग है) यह तथ्य को नहीं बदलता है (इस मामले में) यह अभी भी एक अपरिष्कृत अपवाद होगा । एर्गो, आखिरी return की परवाह किए बिना कभी नहीं मारा जाएगा।

  • यदि आप चाहते हैं कि कोड अंतिम return पर जारी रहे, तो आपका एकमात्र विकल्प कैच टू एक्सेप्शन है ;

  • यदि आप नहीं करते हैं, तो बस इसे वैसे ही छोड़ दें और return हटा दें।

उदाहरण

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

    return returnValue == 1;
}
catch(<some exception>)
{
   // do something
}
finally 
{
    command.Dispose();
}

return false;

प्रलेखन उद्धृत करने के लिए

docs.microsoft.com/en-us/dotnet/csharp/language-reference/…

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

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

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

अंततः

जब कुछ भी हो जो IDisposable इंटरफ़ेस का समर्थन करता है (जो अप्रबंधित संसाधनों को जारी करने के लिए डिज़ाइन किया गया है) using करते using , आप इसे एक using कथन में लपेट सकते हैं। कंपाइलर ऑब्जेक्ट पर try {} finally {} और आंतरिक रूप से Dispose() कॉल try {} finally {} करेगा


ऐसा लगता है, आप कुछ इस तरह की तलाश कर रहे हैं:

private static bool createRecord(string table,
                                 IDictionary<String,String> data,
                                 System.Data.IDbConnection conn,
                                 OdbcTransaction trans) {
  [... some other code ...]

  // Using: do not call Dispose() explicitly, but wrap IDisposable into using
  using (var command = ...) {
    try {
      // Normal flow:
      command.CommandText = sb.ToString();

      // True if and only if exactly one record affected
      return command.ExecuteNonQuery() == 1;
    }
    catch (DbException) {
      // Exceptional flow (all database exceptions)
      return false;
    }
  }
}

कृपया ध्यान दें, कि finally कोई अपवाद नहीं है

finally {
  // This code will be executed; the exception will be efficently re-thrown
}

// And this code will never be reached

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

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

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


आपके कोड पर:

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; // You return here in case no exception is thrown
    } finally {
        command.Dispose(); //You don't have a catch so the exception is passed on if thrown
    }

    return false; // This is never executed because there was either one of the above two exit points of the method reached.
}

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

यह आपके तर्क का दोष है क्योंकि finally ब्लॉक अपवाद को नहीं पकड़ेगा और यह अंतिम रिटर्न स्टेटमेंट तक कभी नहीं पहुंचेगा।


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

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

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

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

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

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

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

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


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

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

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


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

इसलिए, 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