多次处置对象

时间:2012-06-25 15:34:53

标签: c# ca2202

我有以下代码,它使用流来打开和修改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();
    }
}

我最初使用了两个使用块(一个用于MemoryStream,第二个用于WordprocessingDocument),但收到警告CA2202:“对象'流'可以在方法中多次丢弃...”每{{3我将代码修改为上面(将外部使用转换为try),但我仍然收到此警告。

我不确定如何构造此方法以确保在流上只调用一次Dispose。我不想简单地抑制此警告,因为MSDN文章声明您不应该依赖Dispose多次安全地调用。

5 个答案:

答案 0 :(得分:3)

多次处理对象应始终是安全的。来自documentation for Dispose

  

如果多次调用对象的Dispose方法,则该对象必须忽略第一个之后的所有调用。如果多次调用Dispose方法,则该对象不得抛出异常。

话虽如此,使用声明绝对是这里的方式。你收到该方法的唯一原因是你明确处理了不需要的对象,因为using语句应该总是只处理一次对象。

答案 1 :(得分:3)

如果在将stream设置为null之前在using块中抛出异常,则仍可以将流处理两次。试试这个:

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();
    }
}

答案 2 :(得分:3)

MSDN文章中的示例不适合您的原因是他们一旦输入使用块就将流设置为null,而您使用使用块内的流并在之后将流设置为null。如果在stream = null语句之前抛出异常,则在退出使用块时将丢弃stream,然后再在finally块中抛弃。

不幸的是,由于您需要在document更新后访问您的流,因此我没有看到使用他们在您的using语句中设置stream = null的示例的简洁方法来避免多个{ {1}}来电。另一种方法是你可以在try块之外声明Dispose()stream,然后在你的finally中清除它们,就像这样:

document

答案 3 :(得分:2)

using语句处理对象 - 所以基本上你要调用dispose两次

答案 4 :(得分:0)

当您的代码离开WordProcessingDocument周围的使用区块时,它将调用dispose。

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

由于WordProcessingDocument在其构造函数中采用stream的实例,因此在调用WordProcessingDocument.Dispose时将调用该流实例上的dispose。然后输入您调用stream.Dispose()的finally块 - 您现在已在流实例上调用两次Dispose()。