4

次のコードがあります。このコードは、ストリームを使用してOpen XMLドキュメントを開いて変更し、そのストリームの新しいバイナリ表現を保存します。

MemoryStream stream = null;
try
{
    stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))
    {
        OfficeDocument.ModifyDocument(document);
        this.SetBinaryRepresentation(stream.ToArray());
        stream = null;
    }
}
finally
{
    if (stream != null)
    {
        stream.Dispose();
    }
}

私はもともと2つのusingブロック(1つはMemoryStream用、もう1つはWordprocessingDocument用)を使用していましたが、警告CA2202を受け取りました:「オブジェクト'ストリーム'はメソッドで複数回破棄できます...」MSDNの記事に従って、上記のコード(アウターを使用してtryに変換)を実行しましたが、まだこの警告が表示されます。

Disposeがストリームで1回だけ呼び出されるように、このメソッドをどのように構成できるかわかりません。MSDNの記事には、Disposeが安全に何度も呼び出せることに依存してはならないと記載されているため、この警告を単純に抑制したくないと思います。

4

5 に答える 5

6

オブジェクトを複数回廃棄することは常に安全である必要があります。Disposeのドキュメントから:

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

そうは言っても、usingステートメントは間違いなくここに行く方法です。そのメソッドを受け取る唯一の理由は、オブジェクトを明示的に破棄する場合でした。これは、usingステートメントが常にオブジェクトを1回だけ破棄する必要があるため、必須ではありません。

于 2012-06-25T15:38:22.643 に答える
3

MSDNの記事の例が機能しなかった理由は、usingブロックに入るとすぐにストリームをnullに設定するのに対し、usingブロック内のストリームを使用し、後でストリームをnullに設定するためです。stream = nullステートメントの前に例外がスローされた場合stream、usingブロックが終了したときに破棄され、その後、finallyブロックで再び破棄されます。

残念ながら、ストリームを更新した後でストリームにアクセスする必要があるため、usingステートメント内で設定の例を使用して複数の呼び出しを回避するためdocumentのクリーンな方法がわかりません。別の方法は、tryブロックの外側と両方を宣言してから、最後に両方をクリーンアップして、次のようにすることです。stream = nullDispose()streamdocument

MemoryStream stream = null;
WordprocessingDocument document = null;
try
{
    stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    document = WordprocessingDocument.Open(stream, true));

    OfficeDocument.ModifyDocument(document);
    this.SetBinaryRepresentation(stream.ToArray()); 
}
finally
{
    if( document != null)
    {
        document.Dispose();
    }
    // Catch the case where an error occurred before document was defined.
    else
    {
        stream.Dispose();
    }
}
于 2012-06-25T16:01:26.903 に答える
3

ストリームがnullに設定される前に、usingブロックで例外がスローされた場合でも、ストリームは2回破棄される可能性があります。これを試して:

MemoryStream stream = null;
MemoryStream streamToDispose = null;
try
{
    streamToDispose = stream = new MemoryStream();
    stream.Write(this.GetBinaryRepresentation(), 0, this.GetBinaryRepresentation().Length);

    using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))
    {
        streamToDispose = null;
        OfficeDocument.ModifyDocument(document);
        this.SetBinaryRepresentation(stream.ToArray());
    }
}
finally
{
    if (streamToDispose != null)
    {
        streamToDispose.Dispose();
    }
}
于 2012-06-25T15:39:55.233 に答える
2

using ステートメントはオブジェクトを破棄するため、基本的に dispose を 2 回呼び出します。

于 2012-06-25T15:37:47.823 に答える
0

コードが の周りの using ブロックを離れると、WordProcessingDocumentdispose が呼び出されます。

using (WordprocessingDocument document = WordprocessingDocument.Open(stream, true))

WordProcessingDocumentはコンストラクターでのインスタンスを取るため、が呼び出されstreamたときにそのストリーム インスタンスで dispose を呼び出しますWordProcessingDocument.Dispose。次に、呼び出し先の finally ブロックに入りますstream.Dispose()。これで、ストリーム インスタンスで Dispose() を 2 回呼び出しました。

于 2012-06-25T15:58:39.613 に答える