कोशिश / पकड़ + का उपयोग, सही वाक्यविन्यास


189

कौनसा:

using (var myObject = new MyClass())
{
   try
   {
      // something here...
   }
   catch(Exception ex)
   {
      // Handle exception
   }
}

या

try
{
   using (var myObject = new MyClass())
   {
      // something here...
   }
}
catch(Exception ex)
{
   // Handle exception
}

7
बस एक नोट: किसी को केवल अपवादों को पकड़ने के लिए सावधान रहना चाहिए जो वास्तव में संभाला जा सकता है (सही किया जा सकता है ), सिवाय लॉगिंग या लपेटे के।
जॉन सॉन्डर्स

1
कृपया ध्यान रखें कि पिछले }के usingबयान एक अपवाद फेंक कर सकते हैं , जैसा कि यहाँ याद दिला दी
Giulio Caccin

1
यदि आप कोड के पहले ब्लॉक का उपयोग करते हैं तो TIL कि डिबगर (VS में) डिस्पोजल विधि नहीं कहेगा। चूँकि कथन का उपयोग स्वयं ही एक अपवाद को फेंक सकता है, यह मुझे दूसरे ब्लॉक का उपयोग करने में मदद करता है ताकि यह सुनिश्चित किया जा सके finallyकि विवादित विधि कहा जाता है।
शुहोशा

जवाबों:


98

मैं दूसरे को पसंद करता हूं। साथ ही साथ ऑब्जेक्ट के निर्माण से संबंधित ट्रैप त्रुटियां भी हो सकती हैं।


11
मैं इस सलाह से असहमत हूं। यदि आप किसी त्रुटि को फेंकने के लिए ऑब्जेक्ट निर्माण की उम्मीद कर रहे हैं, तो उस अपवाद के किसी भी हैंडल को बाहर जाना होगा । अगर कुछ सवाल है कि हैंडलिंग कहां जानी चाहिए, तो जो अपवाद अपेक्षित है वह कुछ और होना चाहिए — जब तक कि आप किसी ऐसे यादृच्छिक अपवाद को पकड़ने की वकालत नहीं कर रहे हैं, जो अनुमान लगाया जा सकता है या नहीं हो सकता है, जो एक क्लासिक एंटी-पैटर्न है (बाहर) प्रक्रिया या थ्रेड की अनहैंड एक्सेप्शन हैंडलर)।
जेफरी एल व्हाइटलेज

1
@ जेफ्री: मैंने जिस दृष्टिकोण का वर्णन किया है, उसने मेरी अच्छी सेवा की है और मैं लंबे समय से ऐसा कर रहा हूं। किसी ने भी वस्तु निर्माण के असफल होने की उम्मीद के बारे में कुछ नहीं कहा । लेकिन एक ऑपरेशन को लपेटने से जो संभवतः एक tryब्लॉक में विफल हो सकता है , जो आपको एक त्रुटि संदेश पॉप करने की अनुमति देता है यदि कुछ विफल हो जाता है, तो कार्यक्रम में अब उपयोगकर्ता को पुनर्प्राप्त करने और सूचित करने की क्षमता है।
जोनाथन वुड

आपका जवाब सही है, लेकिन सुझाव है कि ट्राई / कैच जारी है है वहाँ हर समय (तुरंत) किया जाना है।
हेंक होल्टरमैन

17
मुझे लगता है कि पहले एक योग्यता के रूप में अच्छी तरह से है, एक DB लेनदेन पर विचार करें using( DBConnection conn = DBFactory.getConnection())जो एक अपवाद के मामले में वापस होने की आवश्यकता होगी। मुझे लगता है कि दोनों का अपना स्थान है।
wfoster

1
यह ऑब्जेक्ट के निपटान से संबंधित त्रुटियों को भी फँसाएगा ।
अहमद इब्राहिम

39

चूंकि एक ब्लॉक का उपयोग सिर्फ एक कोशिश / अंत में ( एमएसडीएन ) का सिंटैक्स सरलीकरण है , व्यक्तिगत रूप से मैं निम्नलिखित के साथ जाऊंगा, हालांकि मुझे संदेह है कि यह आपके दूसरे विकल्प से काफी अलग है:

MyClass myObject = null;
try {
  myObject = new MyClass();
  //important stuff
} catch (Exception ex) {
  //handle exception
} finally {
  if(myObject is IDisposable) myObject.Dispose();
}

4
आपको क्यों लगता है कि एक finallyब्लॉक को जोड़ना usingबयान के लिए बेहतर है ?
कोड़ी ग्रे

10
एक finallyब्लॉक जोड़ना जो एक आईडीसोफोबिक ऑब्जेक्ट का निपटान usingकरता है वह एक स्टेटमेंट करता है। व्यक्तिगत रूप से, मुझे एम्बेडेड usingब्लॉक के बजाय यह पसंद है क्योंकि मुझे लगता है कि यह अधिक स्पष्ट रूप से बताता है कि सब कुछ कहां हो रहा है, और यह सब एक ही "स्तर" पर है। मुझे यह कई एम्बेडेड usingब्लॉकों से भी अधिक पसंद है ... लेकिन यह सिर्फ मेरी प्राथमिकता है।
chezy525

8
यदि आप बहुत अपवाद हैंडलिंग को लागू करते हैं, तो आपको वास्तव में टाइपिंग का आनंद लेना चाहिए! वह "उपयोग" कीवर्ड कुछ समय के लिए आसपास रहा है और इसका अर्थ मेरे लिए काफी स्पष्ट है। और इसका उपयोग अव्यवस्था की मात्रा को न्यूनतम रखने के द्वारा मेरे बाकी कोड को स्पष्ट करने में मदद करता है।
जोनाथन वुड

2
यह गलत है। वस्तु को tryकथन के भीतर निस्तारित करने के लिए कथन के बाहर त्वरित किया जाना चाहिए finally; अन्यथा, यह एक संकलक त्रुटि को फेंक देगा: "
अप्रकाशित

3
तकनीकी रूप से, यह भी संकलित नहीं होगा। Cannot assign null to implicitly-typed local variable;) लेकिन मुझे पता है कि आप क्या मतलब है और व्यक्तिगत रूप से एक ब्लॉक का उपयोग करने के लिए इसे पसंद करेंगे।
कोनेल

20

निर्भर करता है। यदि आप Windows संचार फाउंडेशन (WCF) का उपयोग कर रहे हैं, using(...) { try... }तो सही ढंग से काम नहीं करेगा यदि प्रॉक्सी usingस्टेटमेंट अपवाद स्थिति में है, यानी इस प्रॉक्सी को निपटाने से एक और अपवाद होगा।

व्यक्तिगत रूप से, मैं न्यूनतम हैंडलिंग दृष्टिकोण में विश्वास करता हूं, अर्थात केवल उस अपवाद को संभालता हूं जिसे आप निष्पादन के बिंदु पर जानते हैं। दूसरे शब्दों में, यदि आप जानते हैं कि एक चर का आरंभ usingएक विशेष अपवाद को फेंक सकता है, तो मैं इसे लपेटता हूं try-catch। इसी तरह, अगर usingशरीर के भीतर कुछ हो सकता है, जो सीधे चर से संबंधित नहीं है using, तो मैं इसे tryउस विशेष अपवाद के लिए दूसरे के साथ लपेटता हूं । मैं Exceptionअपने catchईएस में शायद ही कभी उपयोग करता हूं ।

लेकिन मुझे पसंद है IDisposableऔर usingहालांकि मैं शायद पक्षपाती हूं।


19

यदि आपके कैच स्टेटमेंट को एक यूज़िंग स्टेटमेंट में घोषित चर तक पहुंचने की आवश्यकता है, तो अंदर ही आपका एकमात्र विकल्प है।

यदि आपके कैच स्टेटमेंट को डिस्पोज किए जाने से पहले उपयोग में संदर्भित ऑब्जेक्ट की आवश्यकता है, तो अंदर आपका एकमात्र विकल्प है।

यदि आपका कैच स्टेटमेंट अज्ञात अवधि की कार्रवाई करता है, जैसे उपयोगकर्ता को एक संदेश प्रदर्शित करना, और आप ऐसा होने से पहले अपने संसाधनों का निपटान करना चाहेंगे, तो बाहर आपका सबसे अच्छा विकल्प है।

जब भी मेरे पास इसके समान एक scenerio होता है, तो try-catch ब्लॉक आमतौर पर एक अलग विधि में होता है जो कॉल स्टैक का उपयोग करने से आगे बढ़ता है। यह इस तरह से इसके भीतर होने वाले अपवादों को संभालना जानने के लिए एक विधि के लिए विशिष्ट नहीं है।

इसलिए मेरा सामान्य पुनर्मूल्यांकन बाहर का रास्ता है - बाहर का।

private void saveButton_Click(object sender, EventArgs args)
{
    try
    {
        SaveFile(myFile); // The using statement will appear somewhere in here.
    }
    catch (IOException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

10

दोनों मान्य वाक्यविन्यास हैं। यह वास्तव में नीचे आता है कि आप क्या करना चाहते हैं: यदि आप ऑब्जेक्ट को बनाने / निपटाने से संबंधित त्रुटियों को पकड़ना चाहते हैं, तो दूसरे का उपयोग करें। यदि नहीं, तो पहले का उपयोग करें।


8

एक महत्वपूर्ण बात है जिसे मैं यहां बताऊंगा: पहला व्यक्ति निर्माणकर्ता को कॉल करने से उत्पन्न होने वाले किसी अपवाद को नहीं पकड़ेगा MyClass


3

C # 8.0 से, मैं इस तरह का दूसरा उपयोग करना पसंद करता हूं

public class Person : IDisposable
{
    public Person()
    {
        int a = 0;
        int b = Id / a;
    }
    public int Id { get; set; }

    public void Dispose()
    {
    }
}

और फिर

static void Main(string[] args)
    {

        try
        {
            using var person = new Person();
        }
        catch (Exception ex) when
        (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
        ex.TargetSite.MemberType == System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Constructor Person");
        }
        catch (Exception ex) when
       (ex.TargetSite.DeclaringType.Name == nameof(Person) &&
       ex.TargetSite.MemberType != System.Reflection.MemberTypes.Constructor)
        {
            Debug.Write("Error Person");
        }
        catch (Exception ex)
        {
            Debug.Write(ex.Message);
        }
        finally
        {
            Debug.Write("finally");
        }
    }

1

यदि आप जिस ऑब्जेक्ट का उपयोग कर () ब्लॉक में इनिशियलाइज़ कर रहे हैं, वह किसी भी अपवाद को फेंक सकता है तो आपको दूसरे सिंटैक्स के लिए जाना चाहिए अन्यथा दोनों समान रूप से मान्य हैं।

मेरे परिदृश्य में, मुझे एक फ़ाइल खोलनी थी और मैं फ़ाइलपैथ को उस ऑब्जेक्ट के कंस्ट्रक्टर में पास कर रहा था जिसे मैं यूज़िंग () ब्लॉक में इनिशियलाइज़ कर रहा था और अगर फ़ाइलपैथ गलत / खाली है तो यह अपवाद छोड़ सकता है। तो इस मामले में, दूसरा वाक्यविन्यास समझ में आता है।

मेरा नमूना कोड: -

try
{
    using (var obj= new MyClass("fileName.extension"))
    {

    }
}
catch(Exception ex)
{
     //Take actions according to the exception.
}

1

से पर सी # 8.0 , आप सरल बना सकते हैं usingकुछ शर्तों के तहत बयान नेस्टेड ब्लॉक से छुटकारा पाने के, और फिर यह सिर्फ संलग्न ब्लॉक करने के लिए लागू होता है।

तो आपके दो उदाहरण निम्न हो सकते हैं:

using var myObject = new MyClass();
try
{
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}

तथा:

try
{
   using var myObject = new MyClass();
   // something here...
}
catch(Exception ex)
{
   // Handle exception
}

जो दोनों बहुत स्पष्ट हैं; और फिर यह दोनों के बीच चुनाव को कम कर देता है कि आप वस्तु का दायरा क्या चाहते हैं, जहां आप तात्कालिकता त्रुटियों को संभालना चाहते हैं, और जब आप इसे निपटाना चाहते हैं।

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