2008-09-16 5 views
20

सी # में, यदि मैं निर्धारित रूप से गैर-प्रबंधित संसाधनों को साफ़ करना चाहता हूं, तो मैं "उपयोग" कीवर्ड का उपयोग कर सकता हूं। लेकिन कई निर्भर वस्तुओं के लिए, यह आगे और आगे घोंसला बनाने से समाप्त होता है:क्या नेस्टेड "उपयोग" की तुलना में एक बेहतर निर्धारिक निपटान पैटर्न है?

using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open)) 
{ 
    using (BufferedStream bs = new BufferedStream(fs)) 
    { 
     using (StreamReader sr = new StreamReader(bs)) 
     { 
      // use sr, and have everything cleaned up when done. 
     } 
    } 
} 

सी ++ में, मैं विनाशकर्ता उपयोग करने के लिए इस तरह यह करने के लिए सक्षम किया जा रहा करने के लिए इस्तेमाल कर रहा हूँ:

{  
    FileStream fs("c:\file.txt", FileMode.Open); 
    BufferedStream bs(fs); 
    StreamReader sr(bs); 
    // use sr, and have everything cleaned up when done. 
} 

वहाँ एक है ऐसा करने के लिए सी # में बेहतर तरीका है? या मैं घोंसले के कई स्तरों से अटक गया हूँ?

उत्तर

40

आप एक से अधिक usings साथ घोंसला की जरूरत नहीं है:

using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open)) 
using (BufferedStream bs = new BufferedStream(fs)) 
using (StreamReader sr = new StreamReader(bs)) 
{ 
    // all three get disposed when you're done 
} 
+12

यह सिर्फ घोंसला जैसा है - प्रत्येक क्रमिक उपयोग को एक लाइन कोड ब्लॉक के रूप में माना जाता है - अगर एक कथन, sans {} के बारे में सोचें। आपने जो कुछ हासिल किया है वह टैब कुंजी को मारने से परहेज कर रहा है। –

+1

मैं ग्रेग हर्लमैन से सहमत हूं, यह एक स्वरूपण चाल है: जैसे, जबकि, आदि, 'उपयोग' एक एकल कथन को नियंत्रित करता है, लेकिन आप आमतौर पर इसे कथन के ब्लॉक के साथ उपयोग करते हैं। –

+4

खैर, हाँ यह एक स्वरूपण चाल है, लेकिन बिंदु यह है कि यह एक सहायक चाल है, और सी # के लिए नए किसी के लिए स्पष्ट नहीं है। – Eclipse

-1

कथन का उपयोग वाक्यात्मक चीनी कि में धर्मान्तरित है:

आप स्पष्ट रूप से अपने वस्तुओं पर निपटान कॉल कर सकते हैं, लेकिन यह के रूप में सुरक्षित नहीं होगा, अगर उनमें से एक एक अपवाद है, संसाधनों फेंकता है के बाद से ठीक से मुक्त नहीं किया जाएगा।

+0

नोट: गलत। ऑब्जेक्ट प्रारंभिक प्रयास करने के दौरान होता है, भले ही एक से अधिक ऑब्जेक्ट हों। का उपयोग (एक्स ए = एफ(), बी = एफ()) {जी (ए, बी);} एक्स ए = एफ() के समान है; एक्स बी = एफ(); कोशिश करें {जी (ए, बी); } अंत में {बी। निपटान(); a.Dispose(); अपवाद सुरक्षा के लिए एक अंतर है। – Aaron

1

कथन का उपयोग करके घोंसले के बजाय, आप केवल लिख सकते हैं। मैन्युअल रूप से कॉल करें - लेकिन आप निश्चित रूप से किसी बिंदु पर किसी को याद करेंगे।

या तो FxCop या कुछ और चलाएं जो सुनिश्चित कर सकते हैं कि सभी IDISposable- कार्यान्वयन प्रकार के उदाहरणों में एक है। (कॉल), या घोंसले से निपटें।

8

आप बयान एक साथ उपयोग करने से पहले उद्घाटन तो जैसे धनुकोष्ठक रख सकते हैं:

using (StreamWriter w1 = File.CreateText("W1")) 
    using (StreamWriter w2 = File.CreateText("W2")) 
    { 
     // code here 
    } 

http://blogs.msdn.com/ericgu/archive/2004/08/05/209267.aspx

+0

संदर्भ लिंक के लिए धन्यवाद। – Sam

3

आप इस्तेमाल कर सकते हैं चीजों को कम करने के लिए यह वाक्यविन्यास:

using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open)) 
using (BufferedStream bs = new BufferedStream(fs)) 
using (StreamReader sr = new StreamReader(bs)) 
{ 
} 

यह उन दुर्लभ मौकों में से एक है जहां सभी ब्लॉक के लिए {} का उपयोग नहीं करना IMHO समझ में आता है।

0

आप की तरह घुंघराले ब्रेसिज़ छोड़ देते हैं, कर सकते हैं:

using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open)) 
using (BufferedStream bs = new BufferedStream(fs)) 
using (StreamReader sr = new StreamReader(bs)) 
{ 
     // use sr, and have everything cleaned up when done. 
} 

या नियमित रूप से कोशिश का उपयोग अंत में दृष्टिकोण:

FileStream fs = new FileStream("c:\file.txt", FileMode.Open); 
BufferedStream bs = new BufferedStream(fs); 
StreamReader sr = new StreamReader(bs); 
try 
{ 
     // use sr, and have everything cleaned up when done. 
}finally{ 
    sr.Close(); // should be enough since you hand control to the reader 
} 
0

यह एक बहुत बड़ा शुद्ध के लिए प्लस कोड की लाइनों में करता है, लेकिन एक पठनीयता में ठोस लाभ:

using (StreamWrapper wrapper = new StreamWrapper("c:\file.txt", FileMode.Open)) 
{ 
    // do stuff using wrapper.Reader 
} 

कहाँ StreamWrapper यहाँ परिभाषित किया गया है:

private class StreamWrapper : IDisposable 
{ 
    private readonly FileStream fs; 
    private readonly BufferedStream bs; 
    private readonly StreamReader sr; 

    public StreamWrapper(string fileName, FileMode mode) 
    { 
     fs = new FileStream(fileName, mode); 
     bs = new BufferedStream(fs); 
     sr = new StreamReader(bs); 
    } 

    public StreamReader Reader 
    { 
     get { return sr; } 
    } 

    public void Dispose() 
    { 
     sr.Dispose(); 
     bs.Dispose(); 
     fs.Dispose(); 
    } 
} 

कुछ प्रयासों के साथ, स्ट्रीमवापर को अधिक सामान्य और पुन: प्रयोज्य होने के लिए दोबारा प्रतिक्रिया दी जा सकती है।

1

मैं Michael Meadows के पहले की तरह समाधान को लागू किया है, लेकिन उनके StreamWrapper कोड खाते में नहीं ले करता है, तो Dispose() तरीकों सदस्य चर पर बुलाया एक या अन्य कारणों के लिए एक अपवाद फेंक, बाद में Dispose() तों नहीं कहा जा जाएगा और संसाधन लटक सकता है।काम करने के लिए है कि एक के लिए सुरक्षित तरीका है:

 var exceptions = new List<Exception>(); 

     try 
     { 
      this.sr.Dispose(); 
     } 
     catch (Exception ex) 
     { 
      exceptions.Add(ex); 
     } 

     try 
     { 
      this.bs.Dispose(); 
     } 
     catch (Exception ex) 
     { 
      exceptions.Add(ex); 
     } 

     try 
     { 
      this.fs.Dispose(); 
     } 
     catch (Exception ex) 
     { 
      exceptions.Add(ex); 
     } 

     if (exceptions.Count > 0) 
     { 
      throw new AggregateException(exceptions); 
     } 
    } 
+0

इनरएक्सप्शन एक केवल पढ़ने योग्य संपत्ति है। आप इसे लिखने पर कैसे समझते हैं? – supercat

0

ऐसा लगता है कि आम तौर पर धारा बनाते समय बंद एक अन्य स्ट्रीम आधारित नई धारा, एक तो में पारित किया जा रहा बंद हो जाएगा आगे अपने उदाहरण कम करने के लिए:।

सी के तहत

एक फ़ाइल 1.xml नामित:

using (Stream Reader sr = new StreamReader(new BufferedStream(new FileStream("c:\file.txt", FileMode.Open)))) 
{ 
    // all three get disposed when you're done 
} 
+2

नोट: अपवाद सुरक्षा विफल। यदि BufferedStream निर्माता विफल रहता है तो यह फ़ाइलस्ट्रीम को बंद नहीं करेगा। सिंटैक्स का उपयोग करना सी ++ आरएआईआई की तुलना में वास्तव में मुश्किल है। – Aaron

0
इस उदाहरण के लिए

हमें आप मान लें \

एक पाठ बॉक्स textBox1 नामित, बहु लाइन गुणों के साथ सेट करें।

const string fname = @"c:\1.xml"; 

StreamReader sr=new StreamReader(new BufferedStream(new FileStream(fname,FileMode.Open,FileAccess.Read,FileShare.Delete))); 
textBox1.Text = sr.ReadToEnd(); 
+0

नहीं, आप ऐसा नहीं कर सकते - अगर BufferedStream या StreamReader निर्माण के दौरान अपवाद फेंकता है, तब तक फ़ाइलस्ट्रीम का निपटारा नहीं किया जाएगा जब तक कि जीसी सफाई के लिए न हो जाए। आप इस तरह के आसपास तैरने वाली फ़ाइल हैंडल नहीं छोड़ना चाहते हैं। – Eclipse

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

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