2013-03-13 11 views
8

は、以下のコードを検討オブジェクト。複数回

MSDN recommendationよりも、この他のために、他の設計、実装がfinally節で外部使用するストリームを配置することがあります:

Stream stream = null; 
try 
{ 
    stream = new FileStream("file.txt", FileMode.OpenOrCreate); 
    using (StreamWriter writer = new StreamWriter(stream)) 
    { 
     stream = null; 
     // Use the writer object... 
    } 
} 
finally 
{ 
    if(stream != null) 
     stream.Dispose(); 
} 
+5

Microsoftによれば、同じオブジェクトに対してDispose()を複数回呼び出すことができるはずです。 –

+1

@MatthewWatson、その上でマイクロソフトを引用している参考文献はすばらしい –

+0

@MatthewWatson 1回目を使用して既に存在しているオブジェクトを破棄しようとすると、エラーが発生する – CloudyMarble

答えて

3

これはFxCopのは、.NET Frameworkのデザインの選択と対立し、強くある場合である

以下のサンプルでは、​​という名前のフォルダを前提としています。この問題は、ストリームの所有権を前提としたStreamWriterによって引き起こされます。一般に、「成功のピットに落ちる」設計選択では、ほとんどのプログラマはStreamWriterを閉じることでストリームを処理するのに十分であると想定します。特に、Dispose()の代わりにClose()を使用するとそうです。

大部分のケースでうまく機能します。ほとんどの場合、具体的な用途はです。はCryptoStreamです。 CryptoStreamがフラッシュされて破棄される前に、下にあるストリームが閉じられているときに、フラッシングが必要であり、診断不能に誤動作するクラス。 )具体的な問題を容易に認識するにはあまりにも秘密であるにもかかわらず、FxCopの警告が適切な場合)

そして、プログラマが独自のDispose()メソッドを書いて、一回以上呼ばれる。 FxCopの警告が注目されたものですが、実際にはDisposeメソッドが安全であることを知るには十分スマートではありません。

この特定のケースでは、FxCop警告は役に立たないだけです。すべての.NET FrameworkのDispose()メソッドの実装は安全です。 FxCopは.NETフレームワークコードに対してこの種の警告を自動的に抑制します。しかし、マイクロソフトもそれを使用していません。 [SuppressMessage]属性のロットが.NETフレームワークのソースコードにあります。

警告を回避することはあまりにも醜いですし、エラーが発生しやすいです。何も実際に間違っているので、無意味です。 FxCopは "thisと考えていますか?"というメッセージを生成するように設計された単なる診断ツールであることに注意してください。ルールを無視すると、あなたを刑務所に入れる警察官ではありません。それはコンパイラの仕事です。

警告をオフにするには、[SuppressMessage]属性を使用します。

+0

MicrosoftがSupressesMessageを使用して警告を抑制していることを知っているのは本当に面白いです。多くの人がこれらのルールをプログラミングの聖書として見ています。私の場合は、私はstringwriterとtextxmlwriterを使用したので、より複雑でしたので、msdnで提案されているように、stringwriterをnullに設定する前に、文字列をtempvariableに保たなければなりません。 – CloudyMarble

3

この特定のケースのためのソリューションは、the overload of the StreamWriter constructor that lets you tell it not to dispose the underlying streamを呼び出すことです。

残念ながら、これは.Net 4.5の場合のみです。さもなければ、あなたはすでにやっていることをしなければならないでしょう。

また、このスレッドを参照してください。私はそれをしようとすると、Is there any way to close a StreamWriter without closing its BaseStream?

ところで、OPのコードは例外が発生することはありません!存在している:「\ TEST C」:

using System; 
using System.IO; 

namespace Demo 
{ 
    public static class Program 
    { 
     public static void Main(string[] args) 
     { 
      // This does NOT cause any exceptions: 

      using (Stream stream = new FileStream("c:\\test\\file.txt", FileMode.OpenOrCreate)) 
      { 
       using (StreamWriter writer = new StreamWriter(stream)) 
       { 
        writer.Write("TEST"); 
       } 
      } 
     } 
    } 
} 
+0

+1のリンク – CloudyMarble

+0

なぜあなたは例外について話していますか?これはコード分析の警告です。 –

+0

ちょうど情報:私の場合、私はちょうど気がついた.net 4.5は、私のケースの "内部"のストリームがleaveOpenフラグを持たないXmlTextWriterであるので私を助けてくれませんでした! – CloudyMarble