5

現在、次の2つのオブジェクトを使用しています。

using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
{
    // work with ms and bw, both referenced here
}

それは「うまく」機能し、実際ここでも答えです。ただし、VS2012のコード分析ツールを実行すると、次のような警告が表示されます。

CA2202  Do not dispose objects multiple times   
Object 'ms' can be disposed more than once in method '<my method name>'. 
To avoid generating a System.ObjectDisposedException you should not 
call Dispose more than one time on an object.

これは、この状況を処理する別の方法があるかもしれないと私に信じさせますが、それが何であるかはわかりません。

誰かがusing警告なしの方法で単一のブロック内の2つのオブジェクトを使用する「適切な」方法が何であるか知っていますか?

4

4 に答える 4

2

BinaryWriterクラスは、オプションのコンストラクターパラメーターを使用しないように指示しない限り、BinaryWriterを破棄するときに渡される基になるストリームを破棄するように記述されています。バイナリライターは基になるメモリストリームを破棄しており、usingブロック内でも破棄しているため、2回破棄されています。

さて、これはほとんどのクラスにとって実際には問題ではありません。破棄した後に使用しない限り、2回破棄しても問題なく動作するように記述されている必要があります(メモリストリームはそうではありません)。したがって、警告を無視しても問題ありません。警告を消したい場合は、メモリストリームがすでに破棄されているため、メモリストリームを使用から外すことができます。

于 2013-02-09T20:23:52.427 に答える
1

これへのオブジェクト参照が必要ない場合は、正常にMemoryStream機能します

using (var bw = new BinaryWriter(new MemoryStream()))
{
    var memStream = bw.BaseStream as MemoryStream;
}

それ以外の場合は、複数の使用に行きます。特に、.NET Frameworkオブジェクトを使用している場合は、正しい破棄パターンで実装されているためです。

doubleusingステートメントは、2番目のdispose呼び出しを持つ可能性のあるオブジェクトがdisposeパターンを正しく実装していない場合に問題を引き起こす可能性があります。

PS:次のように同じ警告が表示されますか?

using (var memStream = new MemoryStream())
{
    using (var bw = new BinaryWriter(memStream))
    {
        // work with ms and bw
    }
}
于 2013-02-09T19:47:54.823 に答える
1

これが単一の使用ブロックであると仮定するのは正しくありません。この例のコードは、次のようなネストされたusingブロックのシンタックスシュガーです。

using (var ms = new MemoryStream())
{
   using (var bw = new BinaryWriter(ms)) 
   {
    // work with ms and bw, both referenced here
   }
}

これを正しく修正し、警告を回避する単一の方法はありません。内部リソースが外部リソースをラップし、両方が一緒にスコープ外になる場合は、ドキュメントを参照する必要があります。コントラクトに、内部リソースのdisposeメソッドがラップされたオブジェクトのdisposeを呼び出したと記載されている場合は、単に次のことを行う必要はありません。外部リソースをusingブロックに配置します。

そうは言っても、ほとんどのドキュメントではそのような詳細についてはおそらく言及されていません。動作は(副作用を継承して観察することで)自分で確認できますが、そもそも文書化されていないため注意が必要ですが、この動作は将来のリリースで変更される可能性があります。

したがって、非常に心配な場合は、(万が一の場合に備えて)ダブル使用ブロックを残し、警告を抑制して、ブロック全体try{} catch (ObjectDisposedException e) {}を安全なひょうたんに完全に入れることができます。

パラノイアに聞こえますか?使用しているライブラリによって異なります:-)

于 2013-02-09T20:21:54.437 に答える
-4

「using(...){}」は次の目的で使用しないでください。

using (var ms = new MemoryStream())

OSがメモリを管理し、それを「廃棄」するからです。

于 2013-02-09T20:06:26.840 に答える