2010-06-27 7 views
8

मैं इस तरह कोड के बहुत सारे है:सी # CA2000: का उपयोग कर दायरे खोने से पहले वस्तुओं फेंक FileStream/XmlTextReader

FileStream fs = File.Open(@"C:\Temp\SNB-RSS.xml", FileMode.Open); 
using (XmlTextReader reader = new XmlTextReader(fs)) 
{ 
    /* Some other code */ 
} 

यह मैं निम्नलिखित कोड विश्लेषण चेतावनी देता है:

CA2000 : Microsoft.Reliability : In method 'SF_Tester.Run()', object 'fs' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'fs' before all references to it are out of scope. 

अगर मैं पालन सुझाव और मैंने फ़ाइल डाली। एक प्रयोग कथन में खोलें, मुझे यह मिलता है:

CA2202 : Microsoft.Usage : Object 'fs' can be disposed more than once in method 'SF_Tester.Run()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 39 

मैं वीएस -2010 का उपयोग कर रहा हूं और मैं मदद नहीं कर सकता लेकिन लगता है कि मैं कुछ गलत कर रहा हूं लेकिन मुझे यह नहीं दिख रहा है। मैं क्या गलत कर रहा हूँ?

+0

एफवाईआई, "नया एक्सएमएलटीक्स्ट रीडर" .NET 2.0 के बाद से हटा दिया गया है। इसके बजाय 'XmlReader.Create' का उपयोग करें, क्योंकि हंस आपको नीचे दिखाता है। –

+0

जीपर्स ... मुझे नहीं पता था कि XmlTextReader को बहिष्कृत कर दिया गया था। यह अब बहुत अधिक समझ में आता है। धन्यवाद! –

+0

'CA2202' का कारण यह है कि 'रीडर' या 'राइटर' का निपटान करने के लिए उपयोग किए जाने वाले 'फ़ाइलस्ट्रीम' का निपटान भी किया जाता है; इसका मतलब है कि 'लेखक' का निर्माण विफल रहता है, लेकिन यदि यह सफल होता है तो आपको 'fs' का निपटान करना होगा; जो ** testalino ** द्वारा [नीचे जवाब] [http://stackoverflow.com/a/3700444/562906) की ओर जाता है। – PJTraill

उत्तर

15

श्वास, थकाऊ नहीं है। अनुशंसित बनाएं() विधि का उपयोग करके यह सब से बचें:

using (var reader = XmlReader.Create(@"C:\Temp\SNB-RSS.xml")) { 
    //... 
} 
-1

using कथन का उपयोग फ़ाइलस्ट्रीम पर ही XmlTextReader पर ही करें।

http://msdn.microsoft.com/en-us/library/system.io.filestream(VS.71).aspx

ग्रज़, क्रिस।

+0

डाउनवोट क्यों? – XIII

+0

मूल प्रश्न स्पष्ट रूप से कहता है कि उसने यह कोशिश की, और यह एक अलग चेतावनी पैदा करता है। – Brian

1

मैं केवल अनुमान लगा रहा हूं; अब पूर्ण विश्लेषण के माध्यम से जाने के लिए समय नहीं है।

मान लीजिए XmlTextReader कन्स्ट्रक्टर 'पारित होने वाली धारा का स्वामित्व' लेता है, और इसलिए XmlTextReader का निपटान भी अंतर्निहित धारा Dispose होगा। यह आपके द्वारा देखे जाने वाले व्यवहार की व्याख्या करेगा। शायद XmlTextReader कन्स्ट्रक्टर फेंक सकता है, और उस उदाहरण में, fs के बारे में मूल चेतावनी समझ में आ जाएगी। हालांकि,, है कि परिकल्पना, इस कोड

 var fs = File.Open(@"C:\Temp\SNB-RSS.xml", FileMode.Open); 
     XmlTextReader reader = null; 
     try 
     { 
      reader = new XmlTextReader(fs); 
     } 
     finally 
     { 
      if (reader== null) 
      { 
       fs.Dispose(); 
      } 
     } 
     if (reader != null) 
     { 
      using (reader) 
      { 
       /* Some other code */ 
      } 
     } 

दिया मुझे लगता है, सही, लेकिन अभी भी एक नकली चेतावनी अर्जित करता है। यह एक अच्छा उदाहरण की तरह गंध करता है जो स्थैतिक विश्लेषण उपकरणों की सीमाओं को प्रदर्शित करता है।

जैसा कि किसी और ने कहा है, फ़ाइल नाम से पाठक को सीधे बनाने के लिए एक और एपीआई है (XmlReader.Create()), जो यह सब से बचाता है (और दिखाता है कि कैसे अच्छी तरह से डिज़ाइन किए गए परिदृश्य-केंद्रित एपीआई आश्चर्यजनक विविधता के लिए एक अच्छी बात है)।

1

यह एक ज्ञात मुद्दा है

http://connect.microsoft.com/VisualStudio/feedback/details/535118/ca2000-and-ca2202-offer-contradictory-warnings

आप बल्कि XmlTextReader से (समाधान में के रूप में ऊपर) आप प्रासंगिक निर्माता के माध्यम से एक ऐसी ही विधि का उपयोग कर सकता है एक StreamWriter उपयोग कर रहे हैं; जैसे

var sw = new StreamWriter("filename.txt"); 

या

var sw = new StreamWriter("filename.txt", /*append to file = */ false); 

यह प्रलेखन कि क्या निर्माता के प्रथम रूप के ऊपर लिख या किसी फ़ाइल से जोड़ देंगे, से स्पष्ट नहीं है।

11

कोई नहीं के रूप में एक समाधान है कि अभी तक इस मुद्दे को हल करती है प्रदान की है, मैं अक्सर यहां मेरे कार्य समाधान लिख रहा हूँ:

FileStream fs = new FileStream(fileName, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite); 
try 
{ 
    using (var fileWriter = new StreamWriter(fs, encoding)) 
    { 
     fs = null; 
     fileWriter.Write(content); 
    } 
} 
finally 
{ 
    if (fs != null) 
     fs.Dispose(); 
} 

यह CA2000 निकाल देता है।

+0

ठीक है, सभी सुबह खोज रहा है और यह वास्तव में काम करने वाला पहला दृष्टिकोण है। धन्यवाद! मेरा मुद्दा StreamWriter के साथ XMLReader नहीं था, लेकिन उसी सीए नरक बस वही था। – TheZenker

+0

असल में यह सबसे अच्छा जवाब है। देखें http://connect.microsoft.com/VisualStudio/feedback/details/611525/disposable-objects-and-ca2000-ca2202- चेतावनी – ken2k

+0

** testalino **: आप इसे अपने उत्तर में एकीकृत करना चाहते हैं: कारण कि 'एफएस' का उपयोग प्रश्न के रूप में' सीए 2202 'का कारण है कि' रीडर 'या' राइटर 'का निपटान करने के लिए इस्तेमाल किए गए' फाइलस्ट्रीम 'का निपटान भी किया जाता है; इसका मतलब है कि 'लेखक' का निर्माण विफल रहता है, लेकिन यदि यह सफल होता है तो आपको 'fs' का निपटान करना होगा! यह मुझे इन वर्गों के डिजाइन में एक दोष लगता है। मैं नहीं कह सकता कि मुझे आपके पैटर्न का उपयोग करना पसंद है, लेकिन मुझे बेहतर दृष्टिकोण नहीं दिख रहा है; लेखन रैपर वर्ग गलत लगता है। – PJTraill

0

जैसा कि this उत्तर में बताया गया है, इसके आसपास काम करने का एकमात्र तरीका as recommended in CA2202 करना है और ब्लॉक का उपयोग कर बाहरी के बजाय बाहरी प्रयास-अंत ब्लॉक का उपयोग करना है। अंदरूनी उपयोग के अंदर, अंदरूनी उपयोग समाप्त हो जाने के बाद इसे बाहरी आईडीस्पोजेबल ऑब्जेक्ट को नल तक सेट करने के लिए सेट करें।

यहाँ एक सामान्य आवरण है कि यह करता है "सही ढंग से", यानी बुरी तरह से तैयार किया गया XmlReader चारों ओर (धारा इसे प्राप्त करता है? सही तरीके से क्या करना है यह होगा सुनिश्चित नहीं हैं कि के स्वामित्व शायद यह ले लिया है नहीं होना चाहिए) काम करता है

अस्वीकरण: वास्तव में जांची नहीं

public static TResult SafeNestedUsing<TOuter, TInner, TResult>(Func<TOuter> createOuterDisposable, Func<TOuter, TInner> createInnerDisposable, Func<TInner, TResult> body) 
     where TInner : IDisposable 
     where TOuter : class, IDisposable 
    { 
     TOuter outer = null; 
     try 
     { 
      outer = createOuterDisposable(); 
      using (var inner = createInnerDisposable(outer)) 
      { 
       var result = body(inner); 
       outer = null; 
       return result; 
      } 
     } 
     finally 
     { 
      if (null != outer) 
      { 
       outer.Dispose(); 
      } 
     } 
    } 

उदाहरण उपयोग:

SafeNestedUsing<MemoryStream, XmlReader, XmlDocument>(
    ()   => new MemoryStream(array), 
    (memStream) => XmlReader.Create(memStream, xmlReaderSettings), 
    (xmlReader) => 
    { 
     XmlDocument xmlDoc = new XmlDocument(); 
     xmlDoc.Load(xmlReader); 
     return xmlDoc; 
    }); 

यह काफी गुंजाइश है, और आप तर्क दे सकते हैं कि इसके बजाय प्रयास/सेट नल/अंततः पैटर्न को दोहराना बेहतर है। लेकिन घोंसले के उपयोग के दोहराने वाले पैटर्न के लिए मैं हर बार पूरी चीज को दोहराने की बजाय इसे इस तरह से करूंगा।

0

सिर्फ filestream के लिए 'का उपयोग' का उपयोग

using(FileStream fs = new FileStream(fileName, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite)) 
{ 
// some codes here 

} 

FS को संशोधित नहीं है और fs.close() घुंघराले ब्रेसिज़ का उपयोग कर के अंदर प्रयोग नहीं करते।

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