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


135
try {
   // Do stuff
}
catch (Exception e) {
   throw;
}
finally {
   // Clean up
}

उपरोक्त ब्लॉक में अंत में ब्लॉक कब कहा जाता है? ई के फेंकने से पहले या अंत में बुलाया जाता है और फिर पकड़ा जाता है?


14
ps आपको "ई फेंकना नहीं चाहिए;" क्योंकि वह मूल अपवाद के स्टैक ट्रेस को गड़बड़ कर देगा। आपको बस "फेंक" चाहिए। या एक नया अपवाद बनाएं और इनर एक्सेप्शन को "ई" पर सेट करें इससे पहले कि आप इसे फेंक दें।
एरव वाल्टर

24
अंत में कीवर्ड का एक बहुत ही खराब विकल्प होगा यदि यह अंतिम नहीं चला , तो क्या आप नहीं कहेंगे?
एरिक लिपर्ट

@ErvWalter यह अभी भी सच है? मैं इसे VS2017 में दोनों तरह से परख रहा हूं, और यह बिल्कुल एक जैसा प्रतीत होता है। क्या आप कुछ और जानकारी या एक संदर्भ प्रदान कर सकते हैं? धन्यवाद
जेफ Puckett

सिर्फ नामकरण सुझाव का उपयोग करें अपवाद पूर्व घटनाओं / प्रतिनिधियों के लिए रिजर्व ई
आरआर

जवाबों:


138

इसे ई-री-थ्रो (यानी कैच ब्लॉक के निष्पादित होने के बाद) कहा जाएगा

इसे 7 साल बाद संपादित करना - एक महत्वपूर्ण नोट यह है कि यदि eकॉल स्टैक को पकड़ने / पकड़ने के प्रयास से नहीं पकड़ा जाता है या वैश्विक अपवाद हैंडलर द्वारा नियंत्रित किया जाता है, तो finallyब्लॉक कभी भी निष्पादित नहीं हो सकता है


18
और कभी नहीं अगर आप Envrionment.FailFast कहते हैं ()
जोहान्स रूडोल्फ

16
ब्रैंडन के जवाब में कोड की कोशिश करने के बाद, मैं देखता हूं कि finallyयदि पूर्ववर्ती में फेंका गया अपवाद बाहरी - ब्लॉक में catchकभी नहीं पकड़ा गया तो उसे निष्पादित नहीं किया जाता है ! trycatch
एंड्रयू

3
नई जानकारी शामिल करने के लिए अपने (स्वीकृत) उत्तर को संपादित करने के लिए धन्यवाद।
गॉर्डन बीन

3
वे (Microsoft) नए दस्तावेज़ साइट पर इसके बारे में बात करते हैं: docs.microsoft.com/en-us/dotnet/csharp/language-reference/… : "एक संभाले अपवाद के भीतर, संबंधित अंततः ब्लॉक को चलाने की गारंटी है। हालांकि , यदि अपवाद अखंडित है, तो अंत में ब्लॉक का निष्पादन इस बात पर निर्भर करता है कि अपवाद के सुचारू संचालन को कैसे ट्रिगर किया जाता है। यह बदले में, इस बात पर निर्भर करता है कि आपका कंप्यूटर कैसे सेट किया गया है। "
डॉटनेक्स्पार्की

1
ध्यान दें कि "कॉल स्टैक से आगे की कोशिश / कैच ब्लॉक द्वारा पकड़ा गया" में ASP.NET या टेस्ट रनर जैसे फ्रेमवर्क हैंडलर शामिल होंगे। इसे लगाने का एक बेहतर तरीका हो सकता है "यदि आपका प्रोग्राम कैच ब्लॉक के बाद भी चलता है, तो अंत में ब्लॉक निष्पादित होगा।"
ArrowCase

91

क्यों नहीं इसे आज़माएँ:

outer try
inner try
inner catch
inner finally
outer catch
outer finally

कोड के साथ (ऊर्ध्वाधर स्थान के लिए स्वरूपित):

static void Main() {
    try {
        Console.WriteLine("outer try");
        DoIt();
    } catch {
        Console.WriteLine("outer catch");
        // swallow
    } finally {
        Console.WriteLine("outer finally");
    }
}
static void DoIt() {
    try {
        Console.WriteLine("inner try");
        int i = 0;
        Console.WriteLine(12 / i); // oops
    } catch (Exception e) {
        Console.WriteLine("inner catch");
        throw e; // or "throw", or "throw anything"
    } finally {
        Console.WriteLine("inner finally");
    }
}

5
+1, इतनी सरल चीज़ के लिए, आपको वास्तव में इसे आज़माना चाहिए जैसे कि मार्क के पास है। जी जे नेस्टेड ट्राई / कैच के साथ यह दर्शाता हुआ / अंत में :)
एलन चावल

1
@AllenRice अगर मार्क पहले से ही है, तो इसे क्यों आज़माएँ, और मैं मार्क का जवाब ढूंढने के लिए सिर्फ गूगल कर सकता हूँ? या शायद बेहतर हो, अपने आप को आज़माएं, फिर एक एसओ प्रश्न बनाएं और दूसरों के लाभ के लिए स्वयं इसका उत्तर दें।
joshden

8
कृपया ध्यान दें कि यदि आप बाहरी कैच में अपवाद नहीं पकड़ते हैं, तो अंत में कभी भी निष्पादित नहीं होता है !! उस मामले में, आउटपुट हैouter try inner try inner catch Unhandled Exception: System.DivideByZeroException...
एंड्रयू

1
@ और आप सही हैं। स्पष्टीकरण आप यहाँ पा सकते हैं MSDN मैगज़ीन 2008 सितंबर: अनलोडल्ड एक्सेलेरेशन प्रोसेसिंग इन सीएलआर (इसे खोलने के लिए chm को खोलने की आवश्यकता है: फ़ाइल गुण -> सामान्य -> ​​अनलॉक)। यदि आप बाहरी कैच ब्लॉक को "कैच (ArgumentException)" से बदलते हैं, तो कोई भी अंततः ब्लॉक नहीं होगा, क्योंकि CLR को कोई भी "अपवाद हैंडलर नहीं मिल सकता है जो अपवाद को संभालने के लिए सहमत हो" DivideByZeroException।
vladimir

35

यहाँ सभी उत्तरों को पढ़ने के बाद ऐसा लगता है कि अंतिम उत्तर यह निर्भर करता है :

  • यदि आप कैच ब्लॉक के भीतर एक अपवाद को फिर से फेंकते हैं, और वह अपवाद किसी अन्य कैच ब्लॉक के अंदर पकड़ा जाता है, तो सब कुछ प्रलेखन के अनुसार निष्पादित होता है।

  • हालाँकि, यदि पुन: trown अपवाद अखंडित है, तो अंत में कभी निष्पादित नहीं होता है।

मैंने VS2010 w / C # 4.0 में इस कोड नमूने का परीक्षण किया

static void Main()
    {
        Console.WriteLine("Example 1: re-throw inside of another try block:");

        try
        {
            Console.WriteLine("--outer try");
            try
            {
                Console.WriteLine("----inner try");
                throw new Exception();
            }
            catch
            {
                Console.WriteLine("----inner catch");
                throw;
            }
            finally
            {
                Console.WriteLine("----inner finally");
            }
        }
        catch
        {
            Console.WriteLine("--outer catch");
            // swallow
        }
        finally
        {
            Console.WriteLine("--outer finally");
        }
        Console.WriteLine("Huzzah!");

        Console.WriteLine();
        Console.WriteLine("Example 2: re-throw outside of another try block:");
        try
        {
            Console.WriteLine("--try");
            throw new Exception();
        }
        catch
        {
            Console.WriteLine("--catch");
            throw;
        }
        finally
        {
            Console.WriteLine("--finally");
        }

        Console.ReadLine();
    }

यहाँ उत्पादन है:

उदाहरण 1: एक और कोशिश ब्लॉक के अंदर फिर से फेंक दें: -
राउटर आज़माएं
---- भीतर की कोशिश
---- इनर कैच
---- इनर अंत -
राउटर
कैच- राउटर आखिरकार
फुज़ा!

उदाहरण 2: एक और कोशिश ब्लॉक के बाहर फिर से फेंकें:
--try
--catch

अखंडित अपवाद: System.Exception: अपवाद का प्रकार 'System.Exception' फेंका गया था।
ConsoleApplication1.Program.Main () में C: \ स्थानीय स्रोत \ ConsoleApplication1 \ Program.cs: पंक्ति 53


3
शानदार कैच, मुझे इसकी जानकारी नहीं थी!
एंड्रयू

1
ध्यान दें कि अंतिम रूप से आप जो चुनते हैं उसके आधार पर चल सकते हैं: stackoverflow.com/a/46267841/480982
थॉमस वेलर

1
दिलचस्प ... .NET कोर 2.0 पर, अंत में बिना किसी अपवाद के भाग जाता है।
महदी घियासी

दिलचस्प रूप से पर्याप्त है, मैंने अभी .NET कोर 2.0 और .NET फ्रेमवर्क 4.6.1 दोनों में एक परीक्षण किया है और वे दोनों बिना किसी अपवाद के अंत में चलते हैं। क्या यह व्यवहार बदल गया है?
कैमरन बेलस्टीन

24

आपका उदाहरण इस कोड के लिए समान रूप से व्यवहार करेगा:

try {
    try {
        // Do stuff
    } catch(Exception e) {
        throw e;
    }
} finally {
    // Clean up
}

एक तरफ ध्यान दें के रूप में, यदि आप वास्तव में मतलब throw e;(यह है कि, एक ही अपवाद तुम सिर्फ पकड़ा फेंक), यह है बहुत अभी करना बेहतर throw;है, क्योंकि है कि एक नया बनाने की बजाय मूल स्टैक ट्रेस भी सुरक्षित रहेंगे।


मुझे नहीं लगता कि यह सही है। अंत में बाहरी कोशिश ब्लॉक के अंदर होना चाहिए इसके बाहर नहीं
मैथ्यू पिग्राम

@MatthewPigram: आपका क्या मतलब है? finallyब्लॉक वास्तव में बाद चलने लगेंगे catchब्लॉक (भले ही कैच ब्लॉक अपवाद rethrows) है, जो है क्या मेरी टुकड़ा वर्णन करने के लिए कोशिश कर रहा है।
डैनियल प्रीडन

मैं उसके उदाहरण की व्याख्या कैसे करता हूं कि वह एक और कोशिश ब्लॉक के भीतर अंततः एक पकड़ने की कोशिश कर रहा है। अंत में एक कोशिश पकड़ के भीतर एक कोशिश नहीं पकड़
मैथ्यू Pigram

1
@MatthewPigram: मेरे जवाब में कोई "ट्राइ-कैच-आखिर" निर्माण नहीं है। इसमें एक "कोशिश-आखिर" है, और उस tryब्लॉक के अंदर मेरे जवाब में "कोशिश-पकड़" है। मैं दो 2-भाग निर्माणों का उपयोग करके 3-भाग के निर्माण के व्यवहार को समझाने की कोशिश कर रहा हूं। मुझे tryमूल प्रश्न में दूसरे ब्लॉक का कोई संकेत दिखाई नहीं दे रहा है , इसलिए मुझे समझ नहीं आ रहा है कि आपको वह कहाँ मिल रहा है।
डैनियल प्रिडन

12

यदि कैच हैंडलर ब्लॉक के अंदर एक अखंडित अपवाद है, तो अंत में ब्लॉक बिल्कुल शून्य बार कहा जाता है

  static void Main(string[] args)
  {
     try
     {
        Console.WriteLine("in the try");
        int d = 0;
        int k = 0 / d;
     }
     catch (Exception e)
     {
        Console.WriteLine("in the catch");
        throw;
     }
     finally
     {
        Console.WriteLine("In the finally");
     }
  }

आउटपुट:

C: \ उपयोगकर्ताओं \ व्यवस्थापक \ दस्तावेज \ TestExceptionNesting \ बिन \ रिलीज> TestExceptionNesting.exe

कोशिश में

पकड़ में

अखंडित अपवाद: System.DivideByZeroException: शून्य से विभाजित करने का प्रयास किया गया। TestExceptionNesting.Program.Main (String [] args) पर C: \ Users \ व्यवस्थापक \ दस्तावेज \ TestExceptionNesting \ TestExceptionNesting.cs: पंक्ति 22

C: \ उपयोगकर्ताओं \ व्यवस्थापक \ दस्तावेज \ TestExceptionNesting \ बिन \ रिहाई>

मुझे आज एक साक्षात्कार में यह सवाल मिला और साक्षात्कारकर्ता वापस जा रहा है "क्या आप सुनिश्चित हैं कि आखिरकार बुलाया नहीं जाता है?" मैं अनिश्चित था अगर यह एक ट्रिकी प्रश्न था या साक्षात्कारकर्ता के दिमाग में कुछ और था और मेरे लिए डिबग करने के लिए गलत कोड लिखा था, इसलिए मैंने घर आकर इसे बनाने की कोशिश की (निर्माण और रन, कोई डिबगर इंटरैक्शन नहीं), बस अपना दिमाग लगाने के लिए आराम।


जब तक फेंका गया अपवाद किसी अन्य कैच में पकड़ा नहीं जाता है, तब तक स्टैक ऊपर कहीं और होता है, जिस स्थिति में यह निष्पादित हो सकता है यदि उस फेंके गए अपवाद को संभाला जाता है ... या मैं गलत हो सकता हूं ...
tomosius

@tomosius, हां, यही ब्रैंडन का जवाब बताता है। :)
एंड्रयू

@tomosius यही कारण है कि मैंने "यदि कोई अखंड अपवाद है" निर्दिष्ट करके शुरू किया। अगर फेंका गया अपवाद कहीं पकड़ा गया है तो परिभाषा के अनुसार हम एक अलग मामले के बारे में बात कर रहे हैं।
यूसीबियो रुफ़ियान-ज़िल्बर्मान

यह सच नहीं है। कम से कम नेट कोर 3.1 के लिए नहीं। इस कोड के साथ एक सरल नया कंसोल प्रोजेक्ट अपवाद के बाद "अंत में" दिखाता है।
इमेजरो

दिलचस्प है कि व्यवहार बदल गया है, जब मैंने पोस्ट किया था तो .NET कोर भी मौजूद नहीं था;)
Eusebio Rufian-Zilbermann

2

यह बताने का एक सरल तरीका यह भी है कि आपके कोड और नोटिस को डिबग कब किया जाए।


1

C # कंसोल एप्लिकेशन के साथ परीक्षण, अपवाद को फेंक दिए जाने के बाद अंत में कोड निष्पादित किया गया है: "एप्लिकेशन त्रुटि डायलॉग" अस्तित्व में था और आपके द्वारा "प्रोग्राम बंद करें" विकल्प चुनने के बाद, अंत में ब्लॉक को उस कंसोल विंडो में निष्पादित किया गया था। लेकिन अंत में कोड ब्लॉक के अंदर ब्रेकिंग पॉइंट सेट करना, मैं इसे कभी हिट नहीं कर सकता। डिबगर थ्रो स्टेटमेंट पर रुकता रहता है। यहाँ मेरा परीक्षण कोड है:

    class Program
    {
       static void Main(string[] args)
       {
          string msg;
          Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
       }

       static int GetRandomNumber(out string errorMessage)
       {
         int result = 0;
         try
         {
            errorMessage = "";
            int test = 0;
            result = 3/test;
            return result;
         }
         catch (Exception ex)
         {
            errorMessage = ex.Message;
            throw ex;

         }
         finally
         {
            Console.WriteLine("finally block!");
         }

       }
    }

VS2010 में डिबगिंग - .NET फ्रेमवर्क 4.0

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.