39

新しい Visual Studio 2012 は、私がいつも使用している一般的なコードの組み合わせについて不平を言っています。やり過ぎのように思えますが、「念のため」コードで次のことを行いました。

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (var sr = new StreamReader(fs))
    {
        // Code here
    }
}

Visual Studio は、fs を複数回破棄していることを「警告」しています。だから私の質問はこれです、これを書く適切な方法は次のとおりです:

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    var sr = new StreamReader(fs);
    // do stuff here
}

または、この方法で行う必要があります(または、言及されていない他のバリアント)。

var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

using (var sr = new StreamReader(fs))
{
    // Code here
}

StackOverflow でいくつかの質問を検索しましたが、この組み合わせのベスト プラクティスに直接対処するものは見つかりませんでした。

ありがとうございました!

4

7 に答える 7

41

以下は、Microsoft が推奨する方法です。長くてかさばりますが、安全です。

FileStream fs = null;
try
{
    fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    using (TextReader tr= new StreamReader(fs))
    {
        fs = null;
        // Code here
    }
}
finally
{
    if (fs != null)
        fs.Dispose();
}

このメソッドは、スローされる可能性のある例外に関係なく、すべてが破棄されることを常に保証します。たとえば、StreamReaderコンストラクターが例外をスローした場合でも、コンストラクターはFileStream適切に破棄されます。

于 2012-08-17T05:29:46.723 に答える
16

Visual Studio は、fs を複数回破棄していることを「警告」しています。

あなたはそうですが、それで結構です。IDisposable.Disposeのドキュメントには次のように書かれています。

オブジェクトのDisposeメソッドが複数回呼び出された場合、オブジェクトは最初の呼び出し以降のすべての呼び出しを無視する必要があります。Disposeメソッドが複数回呼び出された場合、オブジェクトは例外をスローしてはなりません。

それに基づいて、警告は偽物であり、私の選択はコードをそのままにして、警告を抑制することです。

于 2012-08-18T20:37:46.737 に答える
6

ダンの答えはStreamWriterでしか機能しないように見えるので、これが最も受け入れられる答えかもしれないと私は信じています。(ダンの答えは、StreamReaderで破棄された2回の警告を表示します-Daniel Hilgarthと悪化した専門家が言及しているように、StreamReaderはファイルストリームを破棄します)

using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
    string line;
    while ((line = tr.ReadLine()) != null)
    {
        // Do work here
    }
}

これはDanielHilgarthの回答と非常によく似ており、StreamReaderがFileStreamでdisposeを呼び出すことが明らかになったため、StreamReaderのUsingステートメントを介してdisposeを呼び出すように変更されました(他のすべての投稿によると、ドキュメントを参照)

アップデート:

この投稿を見つけました。それが価値があるもののために。 ストリームリーダーを破棄するとストリームが閉じますか?

于 2012-08-17T18:24:34.393 に答える
2

はい、正しい方法は、最初の選択肢を使用することです。

using (FileStream fs = new FileStream(filePath, FileMode.Open,
                                      FileAccess.Read, FileShare.ReadWrite)) 
{ 
    TextReader tr = new StreamReader(fs); 
    // do stuff here 
} 

その理由は次のとおりです。
Dispose the StreamReaderonlyを破棄すると、FileStream実際に破棄する必要があるのはそれだけです。

. _ FileStream_StreamReader

于 2012-08-17T05:17:19.267 に答える
1

これは、使用した方法StreamReaderでストリームが破棄されたときに破棄されるためです。したがって、ストリームも破棄すると、2回破棄されます。これは欠陥だと考える人もいますが、それでもなおStreamReader存在します。StreamReaderVS 2012(.NET 4.5)では、新しいコンストラクターを使用して、ストリームを破棄しないオプションがあります:http: //msdn.microsoft.com/en-us/library/gg712952

于 2012-08-17T16:06:56.997 に答える
1

2 つのソリューション:

A ) あなたは Reflector または Documentation を信頼して*Readerおり*Writer、基礎となる*Stream. ただし、警告: 例外がスローされた場合は機能しません。したがって、推奨される方法ではありません。

using (TextReader tr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
    // Code here
}

B ) ドキュメントに記載されているように、警告を無視しますThe object must not throw an exception if its Dispose method is called multiple times.。これは、常に使用することをお勧めする方法でusingあり、例外がスローされた場合でも安全であるため、推奨される方法です。

[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
internal void myMethod()
{
    [...]
    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (TextReader tr = new StreamReader(fs))
    {
        // Code here
    }
}
于 2014-04-18T16:52:36.827 に答える
0

この(完全に正当な)質問が生成したすべてのナンセンスを考えると、これは私の好みです:

FileStream fs = null;
TextReader tr= null;
try
{
    fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
    tr= new StreamReader(fs);
    // Code here
}
finally
{
    if (tr != null)
        tr.Dispose();
    if (fs != null)
        fs.Dispose();
}

以下のリンクは、完全に正当な構文を示しています。IMO、この「using」構文は、ネストされた「using」よりもはるかに望ましいです。しかし、私は認めます-それは元の質問を解決しません:

私見では...

于 2012-08-17T19:08:33.890 に答える