2009-03-19 10 views
144

कुछ तरह के बीच में लौटने:एक का उपयोग कर ब्लॉक

using (IDisposable disposable = GetSomeDisposable()) 
{ 
    //..... 
    //...... 
    return Stg(); 
} 

मेरा मानना ​​है कि यह एक वापसी कथन के लिए एक उचित जगह नहीं है, यह क्या है?

उत्तर

149

जैसा कि कई अन्य ने सामान्य रूप से बताया है, यह कोई समस्या नहीं है।

एकमात्र मामला यह आपको कारण बताएगा यदि आप एक उपयोग कथन के बीच में वापस आते हैं और अतिरिक्त रूप से चर का उपयोग करके वापस लौटते हैं। लेकिन फिर, इससे आपको समस्याएं भी मिलेंगी, भले ही आप वापस न आएं और केवल एक चर के संदर्भ में रखें।

using (var x = new Something()) { 
    // not a good idea 
    return x; 
} 

बस के रूप में बुरा

Something y; 
using (var x = new Something()) { 
    y = x; 
} 
+1

बस मैंने आपके द्वारा बताए गए बिंदु के बारे में अपना प्रश्न संपादित करने वाला था। धन्यवाद। – tafa

+0

कृपया मुझे यह समझने में सहायता करें कि यह क्यों बुरा है। मैं एक स्ट्रीम वापस करना चाहता हूं जिसे मैं एक सहायक फ़ंक्शन में छवि प्रसंस्करण के लिए किसी अन्य फ़ंक्शन में उपयोग कर रहा हूं। ऐसा लगता है कि अगर मैं ऐसा करता हूं तो धारा का निपटारा किया जाएगा? –

+1

@ जोहानशेल्डस्की इस मामले में आपके फ़ंक्शन कॉल को उपयोग करने के साथ लपेटा जाना चाहिए। उपयोग करने की तरह (स्ट्रीम x = FuncToReturnStream()) {...} और FuncToReturnStream के अंदर कोई भी उपयोग नहीं कर रहा है। –

14

के बीच यही कारण है कि पूरी तरह से स्वीकार्य है में लौटने के रूप में बिल्कुल ठीक काम करेंगे,। कथन का उपयोग करके सुनिश्चित करता है कि IDISposable ऑब्जेक्ट का निपटारा किया जाएगा चाहे कोई फर्क नहीं पड़ता।

MSDN से

:

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

85

यह बिल्कुल ठीक है - बिल्कुल कोई समस्या नहीं है। आपको विश्वास क्यों है कि यह गलत है?

एक उपयोग कथन केवल कोशिश/आखिरकार ब्लॉक के लिए सिंटैक्टिक चीनी है, और ग्रज़ेनियो का कहना है कि कोशिश ब्लॉक से भी वापस लौटना ठीक है।

वापसी अभिव्यक्ति का मूल्यांकन किया जाएगा, फिर आखिरकार ब्लॉक निष्पादित किया जाएगा, फिर विधि वापस आ जाएगी।

+5

जेम्स कुरान का जवाब बताता है कि मैं क्या सोच रहा था। – tafa

96

यह बिल्कुल ठीक है।

आप जाहिरा तौर पर सोच रहे हैं कि

using (IDisposable disposable = GetSomeDisposable()) 
{ 
    //..... 
    //...... 
    return Stg(); 
} 

आँख बंद करके में अनुवाद किया जाता है:

IDisposable disposable = GetSomeDisposable() 
//..... 
//...... 
return Stg(); 
disposable.Dispose(); 

कौन सा, बेशक, एक समस्या हो सकता है, और using बयान नहीं बल्कि व्यर्थ होगा --- है जो क्यों यह क्या करता है।

कंपाइलर सुनिश्चित करता है कि ब्लॉक को ब्लॉक छोड़ने से पहले ऑब्जेक्ट का निपटारा किया जाता है - चाहे वह ब्लॉक को कैसे छोड़ देता है।

+5

मैं स्पष्ट रूप से था। – tafa

+0

ग्रेट उत्तर @ जेम्स कर्रेन! लेकिन इससे मुझे उत्सुकता मिलती है कि इसका अनुवाद किस प्रकार किया जाता है। या आईएल में केवल स्पष्ट है? (जिसे मैंने वास्तव में पहले पढ़ने की कोशिश नहीं की है)। – Bart

+0

@ बार्ट - मैं इसके बारे में सोचता हूं कि एक अस्थायी चर में वापसी अभिव्यक्ति का मूल्यांकन करने के बाद, फिर निपटान कर रहा है, फिर अस्थायी चर लौटा रहा है। – ToolmakerSteve

-3

शायद यह है कि इस स्वीकार्य है% नहीं 100 सच है ...

आप नेस्टिंग usings और हो रहे हैं तो एक नेस्टेड एक के भीतर से लौट रहे , यह सुरक्षित नहीं हो सकता है।

एक उदाहरण के रूप में इस लें:

using (var memoryStream = new MemoryStream()) 
{ 
    using (var textwriter = new StreamWriter(memoryStream)) 
    { 
     using (var csv = new CsvWriter(textwriter)) 
     { 
      //..write some stuff to the stream using the CsvWriter 
      return memoryStream.ToArray(); 
     } 
    } 
} 

मैं एक DataTable में गुजर रहा था csv के रूप में outputted किया जाना है। बीच में वापसी के साथ, यह स्ट्रीम में सभी पंक्तियां लिख रहा था, लेकिन आउटपुट सीएसवी हमेशा एक पंक्ति (या एकाधिक, बफर के आकार के आधार पर) गायब था। इसने मुझे बताया कि कुछ ठीक से बंद नहीं किया जा रहा था।

सही तरीका यह सुनिश्चित करना है सभी पिछले usings ठीक से निपटारा कर रहे हैं:

using (var memoryStream = new MemoryStream()) 
{ 
    using (var textwriter = new StreamWriter(memoryStream)) 
    { 
     using (var csv = new CsvWriter(textwriter)) 
     { 
      //..write some stuff to the stream using the CsvWriter 
     } 
    } 

    return memoryStream.ToArray(); 
} 
1

कोड bellow दिखाता है कि कैसे using काम कर रहा है:

private class TestClass : IDisposable 
{ 
    private readonly string id; 

    public TestClass(string id) 
    { 
     Console.WriteLine("'{0}' is created.", id); 
     this.id = id; 
    } 

    public void Dispose() 
    { 
     Console.WriteLine("'{0}' is disposed.", id); 
    } 

    public override string ToString() 
    { 
     return id; 
    } 
} 

private static TestClass TestUsingClose() 
{ 
    using (var t1 = new TestClass("t1")) 
    { 
     using (var t2 = new TestClass("t2")) 
     { 
     using (var t3 = new TestClass("t3")) 
     { 
      return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3)); 
     } 
     } 
    } 
} 

[TestMethod] 
public void Test() 
{ 
    Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString()); 
} 

आउटपुट:

'टी 1' बनाया गया है।
't2' बनाया गया है।
't3' बनाया गया है।
'टी 1, टी 2, टी 3 से बनाया गया' बनाया गया है।
'टी 3' का निपटारा किया गया है।
'टी 2' का निपटारा किया गया है।
'टी 1' का निपटारा किया गया है।

निपटारा वापसी कथन के बाद, लेकिन समारोह के निकास से पहले कहा जाता है।

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

  • कोई संबंधित समस्या नहीं^_^