2009-11-12 20 views
10

मैं समझता हूं कि "उपयोग" का बिंदु यह गारंटी देना है कि ऑब्जेक्ट की निपटान विधि को बुलाया जाएगा। लेकिन "उपयोग" कथन के भीतर एक अपवाद कैसे संभाला जाना चाहिए? यदि कोई अपवाद है, तो मुझे कोशिश करने के लिए अपने "उपयोग" कथन को लपेटने की ज़रूरत है। उदाहरण के लिए:'उपयोग' में कैच ब्लॉक क्यों नहीं है?


कहना चलें वहाँ पैरामीटर का उपयोग कर

try 
{ 
    // Exception in using parameter 
    using (SqlConnection connection = new SqlConnection("LippertTheLeopard")) 
    { 
     connection.Open(); 
    } 
} 
catch (Exception ex) 
{ 

} 

या गुंजाइश का उपयोग कर के भीतर एक अपवाद के अंदर वस्तु के निर्माण में बनाई गई एक अपवाद है

using (SqlConnection connection = new SqlConnection()) 
{ 
    try 
    { 
     connection.Open(); 
    } 
    catch (Exception ex) 
    { 

    } 
} 

यह अगर की तरह लगता है मुझे पहले से ही एक कोशिश पकड़ने के साथ एक अपवाद को संभालने की जरूरत है, शायद मुझे ऑब्जेक्ट का निपटान भी संभालना चाहिए। इस मामले में "उपयोग" कथन मुझे बिल्कुल मदद करने के लिए प्रतीत नहीं होता है। मैं "उपयोग" कथन के साथ अपवाद को सही ढंग से कैसे संभाल सकता हूं? क्या इससे कोई बेहतर दृष्टिकोण है कि मुझे याद आ रही है?

SqlConnection connection2 = null; 
try 
{ 
    connection2 = new SqlConnection("z"); 
    connection2.Open(); 
} 
catch (Exception ex) 
{ 

} 
finally 
{ 
    IDisposable disp = connection2 as IDisposable; 
    if (disp != null) 
    { 
     disp.Dispose(); 
    } 
} 

"का उपयोग" खोजशब्द थोड़ा और मीठा हो सकता है ...
यह यकीन है कि यह करने के लिए अच्छा होगा:

using (SqlConnection connection = new SqlConnection()) 
{ 
    connection.Open(); 
} 
catch(Exception ex) 
{ 
    // What went wrong? Well at least connection is Disposed 
} 

उत्तर

5

मेरे पास ऐसे स्थान हैं जहां यह उपयोगी होगा। लेकिन अधिकतर, जब मैं ऐसा करना चाहता हूं तो यह पता चला है कि समस्या मेरे डिजाइन में है; मैं गलत जगह में अपवाद को संभालने की कोशिश कर रहा हूं।

इसके बजाय, मुझे इसे अगले स्तर तक जाने की अनुमति देने की आवश्यकता है — इसे उस फ़ंक्शन में संभाल लें जो इस कोड को सही जगह पर कहलाता है।

+0

+1 यह एक अच्छा बिंदु है। अपवाद शायद अगले स्तर पर संभाला जाना चाहिए। – SwDevMan81

12

using त्रुटि हैंडलिंग के साथ कुछ नहीं किया है। जब आप इस ब्लॉक को छोड़ते हैं तो "निपटान करें" के लिए यह शॉर्टेंड है। आपका दूसरा कोड उदाहरण पूरी तरह से स्वीकार्य है ... क्यों काम करता है?

+0

प्रश्न का मुद्दा यह है कि, वैकल्पिक कैच ब्लॉक का उपयोग क्यों नहीं किया जाता है। जब तक आप माइक्रोसॉफ्ट में काम नहीं करते हैं तब तक यह अधिक उदारवादी है। – Chap

+0

मैं दूसरा उदाहरण नहीं करूंगा। आईएमओ यह गलत स्तर पर एक त्रुटि को संभालने का एक उदाहरण है। इसे कॉलिंग फ़ंक्शन पर 'बबल अप' करने दें। –

+1

@ जोएल चीजों के बड़े दायरे में सहमत हुए, वैसे ही अगर आप उस स्तर पर किसी भी त्रुटि को संभालने का कोई कारण रखते हैं तो मैं ऐसा करूँगा। –

2

एक दिलचस्प विचार है, लेकिन यह थोड़े भ्रामक निम्नलिखित होगा:

using (SqlConnection connection = new SqlConnection()) 
using (SqlCommand cmd = new SqlCommand()) 
{ 
    connection.Open(); 
} 
catch(Exception ex) 
{ 
    // Is connection valid? Is cmd valid? how would you tell? 
    // if the ctor of either throw do I get here? 
} 
+1

आपका उदाहरण मान्य नहीं है। कथन का उपयोग करके "ढेर" एक भाषा सुविधा नहीं है। आपका कोड पहले उपयोग के ब्लॉक के अंदर दूसरे का घोंसला करने के बराबर है। यह घुंघराले ब्रेसिज़ के बिना वापस दो बयानों को वापस लिखने से अलग नहीं है। –

+1

यदि आप व्यक्तिगत रूप से प्रत्येक अपवाद को पकड़ना चाहते हैं तो आप उपयोग ब्लॉक को घोंसला कर सकते हैं। मुझे वास्तव में ओपी का विचार पसंद है, भले ही मुझे यकीन है कि वे इसे भाषा में कभी भी लागू नहीं करेंगे। पर्याप्त उपयोगी नहीं है, और संभावित रूप से भ्रमित है। –

+2

@bytenik: यह अप्रासंगिक है। यह कोड अभी भी लोगों को भ्रमित कर सकता है। इससे कोई फर्क नहीं पड़ता कि यह एक विशेष विशेषता नहीं है। –

8

ब्लॉक का उपयोग एक कोशिश अंत में ब्लॉक के लिए बस वाक्यात्मक चीनी है। आपको एक खंड की जरूरत है, बस एक कोशिश पकड़ अंत का उपयोग करें:

SqlConnection connection; 
try 
{ 
    connection = new SqlConnection(); 
    connection.Open(); 
} 
catch(Exception ex) 
{ 
    // handle 
} 
finally 
{ 
    if (connection != null) 
    { 
     connection.Dispose(); 
    } 
} 

हाँ, यह अपने सैद्धांतिक "का उपयोग कर-पकड़" की तुलना में अधिक कोड है, मैं निर्णय लेता हूं कि भाषा डेवलपर्स ने इसे बहुत ही उच्च प्राथमिकता नहीं माना है, और मैं नहीं कह सकता कि मैंने कभी भी इसका नुकसान महसूस किया है।

+0

जब आप एक अपवाद फेंकते हैं तो आप कथन ब्लॉक से बाहर निकलेंगे ताकि प्रयास/पकड़ बेहतर आईएमओ हो। – ChadNC

+2

@ChadNC: स्पष्ट रूप से आप 'उपयोग' नहीं समझते हैं - यह आपको अपवादों से बचाता है और वैसे भी ऑब्जेक्ट का निपटान करेगा। –

27

क्योंकि आप एक असंबंधित कीवर्ड के अंदर अतिरिक्त कार्यक्षमता 'छुपा' करेंगे।

हालांकि आप हमेशा इसे इस तरह

using (...) try 
{ 
} 
catch (...) 
{ 
} 

और इस तरह लाइन अपने इरादों का प्रतिनिधित्व करता है लिख सकता है - एक का उपयोग कर बयान भी है कि एक कोशिश

+0

यह करने के लिए यह एक छोटा और साफ तरीका है। –

+0

अच्छा, ऐसा लगता है कि उपयोग के अंदर किसी भी त्रुटि को संभालने लगता है, हालांकि यह उपयोग पैरामीटर में अपवाद को कवर नहीं करता है। हालांकि जानना अच्छा है – SwDevMan81

+1

ओह, मुझे यह पसंद है। इच्छा है कि मैं इसे दो बार ऊपर उठा सकता हूं। –

2

आप मेरी राय में चिंताओं मिश्रण कर रहे हैं। संसाधन प्रबंधन (यानी वस्तुओं का निपटान) पूरी तरह से अपवाद हैंडलिंग से अलग है। आपके प्रश्न में वर्णित एक-से-एक मैपिंग केवल एक बहुत ही खास मामला है। आम तौर पर अपवाद हैंडलिंग उसी स्थान पर नहीं होती है क्योंकि उपयोग करने के दायरे समाप्त होते हैं। या आपके पास एक उपयोग ब्लॉक के अंदर कई प्रयास-पकड़ क्षेत्र हो सकते हैं। या ...

+1

अंततः ब्लॉक का उद्देश्य यह सुनिश्चित करना है कि संसाधन साफ ​​हो जाएं। {try {} catch {} अंततः {}} का उपयोग करने के मामले में उपयोग अनावश्यक हो जाता है –

+0

हां, लेकिन 'आखिरकार' का उपयोग क्यों करें? ज्यादातर मामलों में, 'उपयोग' के अंदर 'कोशिश/पकड़' लपेटना स्पष्ट _and_ छोटा है। –

0

मुझे सलाह है कि आप उदाहरण # 1 और # 2 संयुक्त का उपयोग करें। कारण यह है कि आपका उपयोग कथन फ़ाइल को पढ़ सकता है, उदाहरण के लिए, और अपवाद फेंक सकता है (यानी फ़ाइल नहीं मिली)। यदि आप इसे पकड़ नहीं पाते हैं, तो आपके पास एक अनचाहे अपवाद है। उपयोग ब्लॉक के अंदर प्रयास पकड़ ब्लॉक डालने से उपयोग कथन निष्पादित होने के बाद ही अपवादों को पकड़ लिया जाएगा। आपके उदाहरण का संयोजन एक और दो सबसे अच्छा IMHO है।

0

"उपयोग" कथन का उद्देश्य यह सुनिश्चित करना है कि निष्पादन कोड के ब्लॉक से बाहर निकलने पर कुछ प्रकार का क्लीनअप ऑपरेशन होगा, भले ही वह निकास फॉल-थ्रू, अपवाद, या return के माध्यम से हो। जब ब्लॉक किसी भी माध्यम से निकलता है, तो यह के पैरामीटर पर Dispose पर कॉल करेगा। कुछ हद तक, ब्लॉक using पैरामीटर के रूप में निर्दिष्ट किए जाने वाले लाभ के लाभ के लिए मौजूद है, और आम तौर पर उस चीज़ पर ध्यान नहीं दिया जाएगा कि ब्लॉक क्यों निकला था।

कुछ असामान्य मामले हैं जिनके लिए प्रावधान सहायक हो सकते हैं; अतिरिक्त उपयोगिता का उनका स्तर पहले से ही using द्वारा प्रदान किया जाएगा (हालांकि कुछ अन्य सुविधाओं के मुकाबले बेहतर ढंग से बेहतर है जो कार्यान्वयनकर्ता प्रदान करने के लिए उपयुक्त दिखते हैं):

(1) रचनाकारों में एक बहुत ही आम पैटर्न है या वस्तुओं की कारखानों जो अन्य IDisposable वस्तुओं को समाहित करती है; यदि कन्स्ट्रक्टर या फैक्ट्री अपवाद के माध्यम से निकलती है, तो encapsulated ऑब्जेक्ट Dispose डी होना चाहिए, लेकिन यदि यह return के माध्यम से निकलता है तो उन्हें नहीं करना चाहिए। वर्तमान में, इस तरह के व्यवहार try/catch के माध्यम से लागू किया जाना चाहिए, या एक ध्वज के साथ try/finally के संयोजन के द्वारा, लेकिन यह IMHO उपयोगी अगर वहाँ या तो using का एक परिवर्तन है जो केवल Dispose कहेंगे जब यह अपवाद के माध्यम से बाहर निकल गया, वरना एक थे होगा keep using कथन जो using कथन द्वारा नियोजित अस्थायी निकालने के लिए अस्थायी रूप से नियोजित करेगा (using पहचानकर्ता द्वारा पहले नहीं किया जा सकता है, इस तरह की सुविधा को yield return के समान कुछ तरीके से जोड़ा जा सकता है)।

(2) कुछ मामलों में, finally कीवर्ड Exception तर्क स्वीकार करने के लिए विस्तारित होने पर यह सहायक होगा; यदि अपरिवर्तित क्लॉज सामान्य रूप से (रिटर्न या फॉल-थ्रू के माध्यम से) से बाहर निकलता है, और using ब्लॉक interface IDisposeExOnly {void DisposeEx(Exception ex);} और Interface IDisposeEx : IDisposable, IDisposableExOnly {} (संकलन पर) का उपयोग कर सकता है, तो यह अपवाद धारण करेगा, जो संरक्षित खंड (यदि कोई हो), या null का कारण बनता है। समय, लागू होने पर DisposeEx() चयनित, या Dispose() अन्यथा)। यह लेन-देन-आधारित ऑब्जेक्ट्स को सुरक्षित रूप से ऑटो-प्रतिबद्धता का समर्थन करने की अनुमति दे सकता है (यानी पारित अपवाद null, या रोल-बैक गैर-शून्य होने पर प्रतिबद्धता को निष्पादित करने की अनुमति दे सकता है) और Dispose ऐसी स्थितियों में बेहतर लॉगिंग की अनुमति भी देगा जहां Dispose विफल हो गया है संरक्षित खंड के भीतर एक समस्या का परिणाम (उचित बात Dispose के लिए एक अपवाद फेंकने के लिए होगी जो अपवाद को लंबित अपवाद दोनों को समाहित करता है, और परिणामस्वरूप अपवाद होता है, लेकिन वर्तमान में ऐसा करने का कोई साफ तरीका नहीं है उस)।

मुझे नहीं पता कि माइक्रोसॉफ्ट कभी ऐसी विशेषताएं जोड़ देगा या नहीं; पहला, और दूसरे का पहला भाग, भाषा स्तर पर पूरी तरह से संभाला जाएगा। दूसरे का उत्तरार्द्ध फ्रेमवर्क स्तर पर होगा।

संबंधित मुद्दे