2012-05-23 18 views
11

के अंत में के बजाय का उपयोग करते हुए मैं इस पैटर्न देखा है अब कुछ समय:पकड़

 bool success = false; 
     try 
     { 
      DoSomething(); 
      success = true; 
     } 
     finally 
     { 
      if (!success) 
       Rollback(); 
     } 

और मैं सोच रहा है: क्यों इस पुनरावर्तन के लिए पकड़ का उपयोग करने से बेहतर है?

 try 
     { 
      DoSomething(); 
     } 
     catch 
     { 
      Rollback(); 
      throw; 
     } 

सुनिश्चित करने के दो तरीकों के बीच मतभेद क्या हैं विफलता पर परिवर्तन वापस आ गए हैं?

उत्तर

0

यहां स्पष्ट लक्ष्य Rollback को किसी भी त्रुटि की स्थिति में बुलाया जाना है। दोनों कोड स्निपेट इस लक्ष्य को पूरा करते हैं। पहला अंततः उपयोग करता है, जो हमेशा चलता है, जो सत्यापित करता है कि try ब्लॉक की अंतिम पंक्ति सफलतापूर्वक पहुंच गई थी। दूसरा किसी भी त्रुटि को पकड़ता है, लेनदेन को वापस ले जाता है, और फिर पकड़ा गया अपवाद फेंकता है। स्निपेट का नतीजा यह है कि किसी भी अपवाद को फेंकने के परिणामस्वरूप रोलबैक हो जाएगा जबकि अभी भी अगले स्तर तक बुलबुला होगा।

आपने बताया कि परियोजना जावा से पोर्ट की गई थी। जावा में, आप re-throw an exception इसी तरह से throw; का उपयोग कर सी # में कैसे कर सकते हैं। आप throw a new exception भी कर सकते हैं जो कॉल स्टैक (एट अल) को बनाए रखेगा। दूसरा सी # में थोड़ा स्पष्ट/सरल है (हालांकि बहुत कुछ नहीं) और पहले जावा में वास्तव में लिखित रूप में काम करने का लाभ है।

+0

यह समझ में आता है। मुझे एहसास नहीं हुआ कि जावा आपको उत्तेजना को सही ढंग से पुनर्स्थापित करने की अनुमति नहीं देता है। और यहां मैं सोच रहा था कि यह महत्वपूर्ण वर्गों और पसंदों के साथ कुछ करने जा रहा था ... – configurator

+0

@configurator: अब जब आप इसका जिक्र करते हैं, तो मुझे लगता है कि वास्तव में [प्रतिबंधित निष्पादन क्षेत्र] (http://msdn.microsoft.com/en-us/library/ms228973.aspx)। – dtb

+4

-1 "जावा में" अपवाद को फिर से फेंकने का कोई तरीका नहीं है "- ['फेंक ई' के अलावा, यह है (http://stackoverflow.com/a/1097539/265143)। –

1

finally हमेशा अपवादों को पकड़ने पर न केवल निष्पादित किया जाता है।

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

+2

लेकिन जब कोई अपवाद नहीं है तो 'सफलता' झूठी होगी, इसलिए आखिरकार खंड एक नो-ऑप है। – configurator

+0

@configurator, हाँ, मेरा अपडेट देखें। –

+0

जावा पृष्ठभूमि टिप्पणी उस परियोजना को समझ में आती है जहां मैंने देखा है कि यह वास्तव में जावा से पोर्ट किया गया था। – configurator

2

finally कथन आमतौर पर संसाधनों की सफाई के लिए उपयोग किया जाता है। Rollback() विधि का उपयोग करने के लिए ठीक हो सकता है यदि अपवाद केवल लेनदेन को वापस करने का एकमात्र कारण नहीं है। Close() या Dispose() विधियां मुख्य रूप से ब्लॉक में समाप्त होने के लिए प्रमुख उम्मीदवार हैं।

हालांकि, आप अपवाद को फेंकने वाले कुछ भी निष्पादित नहीं करना चाहते हैं।

+4

इस उत्तर में प्रश्न के साथ बहुत कुछ नहीं है ... – configurator

+0

जैसा कि मैंने उल्लेख किया है, अंत में बयान में संसाधन सफाई करना आम बात है। इस तरह आपको पुनर्स्थापित करने की ज़रूरत नहीं है। –

+0

@configurator मजाकिया, यह अभी तक उच्चतम रेटेड है, और इसके समान अन्य भी हैं, शायद आपकी इच्छा के अनुरूप प्रतिक्रियाओं को और अधिक जानने के लिए प्रश्न संपादित करें? –

4

मैं यहां कुछ कोड पोस्ट करता हूं भले ही यह वास्तव में प्रश्न से संबंधित नहीं है (बाद में हटा देगा)।

इस कार्यक्रम के साथ

:

using System; 

namespace testcs 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      try 
      { 
       try 
       { 
        foo(); 
        foo(); 
        foo(); 
       } 
       catch 
       { 
        throw; 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.ToString()); 
      } 
     } 

     private static void foo() 
     { 
      throw new Exception("oops"); 
     } 
    } 
} 

स्टैक ट्रेस (! लाइन नंबर पर देखने के) संरक्षित है लेकिन main समारोह के अंदर आप "रेखा 19" दिखाई देगा, लाइन जहां throw बजाय सच है लाइन जहां foo() कहा गया है (लाइन 13)।

+3

+1, पॉइंट लिया गया, नमूना बनाने के लिए समय निकालने के लिए धन्यवाद। मुझे नहीं लगता कि आपको इसे हटाने की ज़रूरत है, क्योंकि यह प्रश्न में दो विधियों के बीच अंतर को दर्शाता है (और यह निश्चित रूप से टिप्पणी के लिए बहुत लंबा है)। – Heinzi

2

मुझे यकीन है कि अगर यह सिर्फ anecdotal evidence नहीं है नहीं कर रहा हूँ, लेकिन मैं व्यक्तिगत रूप से एक बहुत ही व्यावहारिक कारण के लिए इस पद्धति का इस्तेमाल किया है: जहां अपवाद पहले में होता है DoSomething एक अपवाद फेंकता है, विजुअल स्टूडियो डीबगर DoSomething में टूट जाएगा संस्करण, जबकि यह दूसरे संस्करण में throw; पर टूट जाएगा। यह Rollback से पहले आवेदन स्थिति का निरीक्षण करने की अनुमति देता है सब कुछ साफ कर दिया है।

Screenshot

2

आप इस विशेष कोड अपवाद आप किस प्रकार का उपयोग कर रहे हैं पकड़ने में परवाह नहीं है, तो:

try 
{ 
    DoSomething(); 
    ok = true; 
} 
finally 
{ 
    if(!ok)Rollback(); 
} 

यह 100% के लिए अपने मूल रूप में कॉल स्टैक सुरक्षित करेगा। इसके अलावा, आप इस तरह अपवाद की मशीन का उपयोग करता है, तो:

try 
{ 
    DoSomething(); 
    ok = true; 
} 
catch(FirstExcetionType e1) 
{ 
    //do something 
} 
catch(SecondExcetionType e2) 
{ 
    //do something 
} 
catch(Exception e3) 
{ 
    //do something 
} 
finally 
{ 
    if(!ok)Rollback(); 
} 

अंत में अंत में उपयोग करते हुए हर एक को पकड़ने के बयान से रोलबैक बुला की तुलना में अपने कोड अधिक पठनीय बना सकते हैं।