यदि मैं कथन का उपयोग करने से पहले समाप्त हो जाता हूं तो क्या होगा? क्या निस्तारण कहा जाएगा?


115

मैं निम्नलिखित कोड है

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}

dispose()विधि के अंत में कहा जाता है usingबयान धनुकोष्ठक }है ना? चूंकि मैं बयान returnके अंत से पहले using, क्या MemoryStreamवस्तु को ठीक से निपटाया जाएगा? यहाँ क्या हुआ?


4
@ जॉन: डुप्लिकेट का पता लगाएं, फिर उस स्थिति में बंद करने के लिए वोट करें।
नोल्डोरिन

@Noldorin: मैं क्योंकि मैं सोचा कि यह इस पर एक शिकार की तलाश में चला गया, चाहिए से पहले कहा गया है, लेकिन मैं एक खोजने में असमर्थ था। मुझे लगता है कि वहाँ अभी भी आसान सवाल हैं। :)
Randolpho

@ जोन्ह और @ नोल्डोरिन - डुप्लिकेट्स प्रस्तुत किए जाते थे जब सवाल बनता था, यह "समान प्रश्नों" की खोज करता है, एक विशेषता लोगों को पर्याप्त उपयोग नहीं करने लगती है।
एडम हल्ड्सवर्थ

@ एडम: जाओ इसे अपने आप कोशिश करो। शीर्षक कॉपी / पेस्ट करें और देखें कि डुप्लिकेट को सिस्टम द्वारा प्रस्तुत किया जाता है। मैं तुम्हें एक संकेत देता हूँ: जवाब कोई नहीं है। यदि आप Google या SO की खोज के माध्यम से खोज करते हैं। ऐसा प्रतीत होता है कि यह प्रश्न पहले नहीं पूछा गया है।
Randolpho

आआफ ... मैं उसे वापस लेता हूं। मैंने अभी कुछ ही समर्पित खोज के बाद एक पास डुप्लिकेट पाया: stackoverflow.com/questions/2641692/… अब, सवाल पूरी तरह से अलग तरह से पूछा जाता है, लेकिन अंतिम प्रश्न बहुत अधिक समान है। मुझे लगता है कि हम इस सब पर विचार कर सकते हैं।
Randolpho

जवाबों:


167

हां, Disposeबुलाया जाएगा। जैसे ही निष्पादन को usingब्लॉक का दायरा छोड़ दिया जाता है , भले ही इसका मतलब यह हो कि ब्लॉक छोड़ने के लिए क्या किया गया है, चाहे वह ब्लॉक के निष्पादन का अंत हो, एक returnबयान, या एक अपवाद।

जैसा कि @Noldorin सही ढंग से बताता है, usingकोड में एक ब्लॉक का उपयोग करके try/ में संकलित किया जाता है finally, Disposeजिसे finallyब्लॉक में बुलाया जाता है । उदाहरण के लिए निम्नलिखित कोड:

using(MemoryStream ms = new MemoryStream())
{
     //code
     return 0;
}

प्रभावी रूप से बन जाता है:

MemoryStream ms = new MemoryStream();
try
{
    // code
    return 0;
}
finally
{
    ms.Dispose();
}

इसलिए, क्योंकि ब्लॉक के निष्पादन को समाप्त finallyकरने के बाद निष्पादित करने की गारंटी दी गई है try, इसके निष्पादन पथ की परवाह किए बिना, Disposeकॉल करने की गारंटी दी जाती है, चाहे जो भी हो।

अधिक जानकारी के लिए, यह MSDN आलेख देखें

परिशिष्ट:
जोड़ने के लिए बस थोड़ा सा चेतावनी: क्योंकि Disposeबुलाया जाने की गारंटी है, यह लगभग हमेशा एक अच्छा विचार है यह सुनिश्चित करने के लिए कि आप Disposeकभी भी अपवाद नहीं फेंकते जब आप इसे लागू करते हैं IDisposable। दुर्भाग्य से, वहाँ कोर पुस्तकालय में कुछ वर्गों है कि कर रहे हैं ऐसा कुछ निश्चित परिस्थितियों में फेंक जब Disposeमैं अपने आप को देख रहा हूँ, WCF सेवा संदर्भ / क्लाइंट प्रॉक्सी - कहा जाता है! - और जब ऐसा होता है तो मूल अपवाद को ट्रैक करना बहुत मुश्किल हो सकता है यदि Disposeअपवाद स्टैक के दौरान बुलाया गया था, क्योंकि मूल अपवाद Disposeकॉल द्वारा उत्पन्न नए अपवाद के पक्ष में निगल जाता है । यह भयावह रूप से निराशाजनक हो सकता है। या कि निराशा से पागल हो रहा है? इन दो में से एक। शायद दोनो।


4
मुझे लगता है कि आप पाएंगे कि यह अंततः एक कॉल के साथ अंत में एक कोशिश-अंत में प्रभावी रूप से संकलित है Dispose, इसलिए यह प्रभावी finallyरूप से कार्यान्वयन को बंद कर रहा है , जैसा कि आप वर्णन करते हैं।
नोल्डोरिन

@ नोल्डोरिन: बिल्कुल। हालांकि मुझे लगता है कि मैं इसके बारे में स्पष्ट हो सकता हूं। आगामी संपादन ....
Randolpho

1
यह भी ध्यान दें कि कुछ परिस्थितियाँ हैं जिनमें अंत में ब्लॉक निष्पादित करने की गारंटी नहीं है, जैसे कि Environment.FailFast और यदि StackOverFlowException होती है।
क्रिस्टोफर मैकअटैकनी जू

@ C.McAtackney: एक अच्छा बिंदु। इसके अलावा, IIRC, OutOfMemoryException; मूल रूप से यदि आप अपवाद को नहीं पकड़ सकते क्योंकि यह एक महत्वपूर्ण निष्पादन विफलता है, तो डिस्पोज़ को नहीं बुलाया जाएगा। बेशक, ऐसे मामले में कार्यक्रम को क्रैश करने की गारंटी दी जाती है, साथ ही इसे आवंटित की गई किसी भी मेमोरी के साथ, इसलिए 99.9% मामलों में यह एक गैर-मुद्दा है, जब तक कि आप अपने डिसपोजल तरीके से फाइल में लिखने जैसा विजयी सामान नहीं कर रहे हैं। । तबाही कार्यक्रम के अलावा, कि है।
Randolpho

आपको WCF के साथ 'यूज़ ()' स्टेटमेंट का उपयोग कभी नहीं करना चाहिए - अधिक जानकारी के लिए इस लेख का संदर्भ लें । यहाँ एक स्निपेट है जिसका उपयोग मैं WCF परदे के पीछे करता हूँ: 'WCFProxy variableName = null; {चर नाम = नया WCFProxy () आज़माएं; // TODO कोड यहाँ variableName.Proxy.Close (); variableName.Dispose (); } catch (Exception) {if (variableName! = null && variableName.Proxy! = null) {variableName.Proxy.Abort (); } फेंकना; } '
डेव ब्लैक

18

usingकथन बिल्कुल try ... finallyब्लॉक की तरह व्यवहार करते हैं , इसलिए हमेशा किसी भी कोड निकास पथ पर निष्पादित होंगे। हालांकि, मेरा मानना ​​है कि वे बहुत कम और दुर्लभ स्थितियों के अधीन हैं जिनमें finallyब्लॉक नहीं कहा जाता है। एक उदाहरण जो मुझे याद है वह यह है कि यदि अग्रगामी धागा बाहर निकलता है जबकि पृष्ठभूमि थ्रेड सक्रिय होते हैं: जीसी के अलावा सभी थ्रेड्स रोक दिए जाते हैं, जिसका अर्थ है finallyकि ब्लॉक नहीं चलाए जाते हैं।

स्पष्ट रूप से संपादित करें: वे तर्क के अलावा उसी तरह का व्यवहार करते हैं जो उन्हें आईडीसोफ्रीबल ऑब्जेक्ट्स, डीओएच को संभालने देता है।

बोनस सामग्री: उन्हें स्टैक किया जा सकता है (जहां प्रकार भिन्न होते हैं):

using (SqlConnection conn = new SqlConnection("string"))
using (SqlCommand comm = new SqlCommand("", conn))
{

}

और अल्पविराम-सीमांकित (जहां प्रकार समान हैं):

using (SqlCommand comm = new SqlCommand("", conn), 
       SqlCommand comm2 = new SqlCommand("", conn))
{

}

4

आपकी मेमोरीस्ट्रीम ऑब्जेक्ट को ठीक से निपटाया जाएगा, इसके बारे में चिंता करने की कोई आवश्यकता नहीं है।



0

आप इसे संकलित करने के बाद रिफ्लेक्टर में अपने कोड को देखें। आपको पता चलेगा कि कंपाइलर कोड को यह सुनिश्चित करने के लिए रिफलेक्ट करता है कि डिस्प्यूट स्ट्रीम में कहा जाता है।

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