c# - क्या होता है यदि आखिरकार ब्लॉक अपवाद फेंकता है?




exception exception-handling (8)

यदि आखिरकार ब्लॉक एक अपवाद फेंकता है, तो वास्तव में क्या होता है?

विशेष रूप से, क्या होता है यदि अपवाद को आखिरकार ब्लॉक के माध्यम से मिडवे फेंक दिया जाता है। क्या इस ब्लॉक में शेष बयान (बाद में) आते हैं?

मुझे पता है कि अपवाद ऊपर फैल जाएगा।


यदि आखिरकार ब्लॉक एक अपवाद फेंकता है तो वास्तव में क्या होता है?

वह अपवाद ऊपर और ऊपर फैलता है, और उच्च स्तर पर (कर सकते हैं) संभाला जाएगा।

आपका आखिरी ब्लॉक उस बिंदु से परे पूरा नहीं होगा जहां अपवाद फेंक दिया गया है।

यदि अंत में ब्लॉक पहले के अपवाद के संचालन के दौरान निष्पादित कर रहा था तो पहला अपवाद खो गया है।

सी # 4 भाषा विशिष्टता § 8.9.5: यदि अंत में ब्लॉक एक और अपवाद फेंकता है, तो मौजूदा अपवाद की प्रक्रिया समाप्त हो जाती है।


अपवाद प्रचारित है।


इन सवालों के लिए मैं आमतौर पर विजुअल स्टूडियो में एक खाली कंसोल एप्लिकेशन प्रोजेक्ट खोलता हूं और एक छोटा सा नमूना प्रोग्राम लिखता हूं:

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            try
            {
                throw new Exception("exception thrown from try block");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Inner catch block handling {0}.", ex.Message);
                throw;
            }
            finally
            {
                Console.WriteLine("Inner finally block");
                throw new Exception("exception thrown from finally block");
                Console.WriteLine("This line is never reached");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Outer catch block handling {0}.", ex.Message);
        }
        finally
        {
            Console.WriteLine("Outer finally block");
        }
    }
}

जब आप प्रोग्राम चलाते हैं तो आपको सटीक ऑर्डर दिखाई देगा जिसमें catch और finally ब्लॉक निष्पादित किए जाते हैं। कृपया ध्यान दें कि अपवाद के बाद आखिरकार ब्लॉक में कोड निष्पादित नहीं किया जाएगा (वास्तव में, इस नमूना कार्यक्रम में विजुअल स्टूडियो आपको चेतावनी भी देगा कि उसे पहुंचने योग्य कोड नहीं मिला है):

Inner catch block handling exception thrown from try block.
Inner finally block
Outer catch block handling exception thrown from finally block.
Outer finally block

अतिरिक्त टिप्पणी

जैसा कि माइकल दमातोव ने बताया, try ब्लॉक से एक अपवाद "खाया जाएगा" यदि आप इसे (आंतरिक) catch ब्लॉक में संभाल नहीं पाते हैं। वास्तव में, फिर से फेंक दिया अपवाद के ऊपर उदाहरण में बाहरी पकड़ ब्लॉक में दिखाई नहीं देता है। निम्नलिखित थोड़ा संशोधित नमूना पर और भी स्पष्ट रूप से देखने के लिए:

using System;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            try
            {
                throw new Exception("exception thrown from try block");
            }
            finally
            {
                Console.WriteLine("Inner finally block");
                throw new Exception("exception thrown from finally block");
                Console.WriteLine("This line is never reached");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Outer catch block handling {0}.", ex.Message);
        }
        finally
        {
            Console.WriteLine("Outer finally block");
        }
    }
}

जैसा कि आप आउटपुट से देख सकते हैं आंतरिक अपवाद "खो गया" है (यानी अनदेखा):

Inner finally block
Outer catch block handling exception thrown from finally block.
Outer finally block

एक अपवाद फेंकना जबकि एक और अपवाद सक्रिय है, परिणामस्वरूप दूसरे अपवाद को दूसरे (बाद में) अपवाद द्वारा प्रतिस्थापित किया जाएगा।

यहां कुछ कोड दिया गया है जो दिखाता है कि क्या होता है:

    public static void Main(string[] args)
    {
        try
        {
            try
            {
                throw new Exception("first exception");
            }
            finally
            {
                //try
                {
                    throw new Exception("second exception");
                }
                //catch (Exception)
                {
                    //throw;
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
  • कोड चलाएं और आपको "दूसरा अपवाद" दिखाई देगा
  • कोशिश करें और पकड़ने के बयान को कम करें और आपको "पहला अपवाद" दिखाई देगा
  • फेंक भी असम्बद्ध; कथन और आप फिर से "दूसरा अपवाद" देखेंगे।

मुझे ऐसा स्ट्रीम बंद करने की कोशिश में त्रुटि को पकड़ने के लिए ऐसा करना पड़ा जो अपवाद के कारण कभी नहीं खोला गया था।

errorMessage = string.Empty;

try
{
    byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlFileContent);

    webRequest = WebRequest.Create(url);
    webRequest.Method = "POST";
    webRequest.ContentType = "text/xml;charset=utf-8";
    webRequest.ContentLength = requestBytes.Length;

    //send the request
    using (var sw = webRequest.GetRequestStream()) 
    {
        sw.Write(requestBytes, 0, requestBytes.Length);
    }

    //get the response
    webResponse = webRequest.GetResponse();
    using (var sr = new StreamReader(webResponse.GetResponseStream()))
    {
        returnVal = sr.ReadToEnd();
        sr.Close();
    }
}
catch (Exception ex)
{
    errorMessage = ex.ToString();
}
finally
{
    try
    {
        if (webRequest.GetRequestStream() != null)
            webRequest.GetRequestStream().Close();
        if (webResponse.GetResponseStream() != null)
            webResponse.GetResponseStream().Close();
    }
    catch (Exception exw)
    {
        errorMessage = exw.ToString();
    }
}

यदि webRequest बनाया गया था लेकिन कनेक्शन के दौरान एक कनेक्शन त्रुटि हुई

using (var sw = webRequest.GetRequestStream())

तो आखिरकार कनेक्शन को बंद करने की कोशिश कर रहे अपवाद को पकड़ लिया जाएगा, जिसे सोचा गया था क्योंकि वेबरक्वेट बनाया गया था।

अगर आखिर में अंदरूनी कोशिश नहीं की गई, तो वेब कोड की सफाई करते समय यह कोड एक अनचाहे अपवाद का कारण बन जाएगा

if (webRequest.GetRequestStream() != null) 

वहां से कोड उत्पन्न होने वाली त्रुटि को सही ढंग से संभालने के बिना बाहर निकल जाएगा और इसलिए कॉलिंग विधि के लिए समस्याएं उत्पन्न हो रही हैं।

उम्मीद है कि यह एक उदाहरण के रूप में मदद करता है


मूल (एक और स्पष्ट) स्निपेट को "मूल अपवाद" ( try ब्लॉक में फेंक दिया गया) और "अंततः अपवाद" ( finally ब्लॉक में फेंक दिया गया) को बचाने के लिए स्निपेट, यदि मूल आपके लिए अधिक महत्वपूर्ण है:

try
{
    throw new Exception("Original Exception");
}
finally
{
    try
    {
        throw new Exception("Finally Exception");
    }
    catch
    { }
}

जब उपरोक्त कोड निष्पादित किया जाता है, तो "मूल अपवाद" कॉल स्टैक को प्रसारित करता है, और "अंत में अपवाद" खो जाता है।


यह एक अपवाद फेंकता है;) आप किसी अन्य पकड़ खंड में उस अपवाद को पकड़ सकते हैं।


public void MyMethod()
{
   try
   {
   }
   catch{}
   finally
   {
      CodeA
   }
   CodeB
}

जिस तरह से कोडेए और कोडेबी द्वारा दिए गए अपवादों को संभाला जाता है वही है।

finally ब्लॉक में फेंक दिया गया अपवाद कुछ खास नहीं है, इसे कोड बी द्वारा अपवाद फेंकने के रूप में माना जाता है।







try-catch-finally