Fix an object multiple times

I have the following code that uses a stream to open and modify an Open XML document, and then save a new binary representation of this stream:

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

I initially used the two blocks used (one for MemoryStream and one for WordprocessingDocument), but I got warning CA2202: "Object" thread "can be deleted more than once in a method ..." In the MSDN article , I changed the code above (converting external use per attempt), but I still get this warning.

I'm not sure how I can structure this method to ensure that Dispose is called exactly once in the stream. I would prefer not just to suppress this warning, as the MSDN article states that you should not rely on Dispose, which can be safely called multiple times.

+4
source share
5 answers

The reason that the example from the MSDN article didn’t work for you is because they set the stream to zero as soon as they enter the use block , while you use the stream inside your use block and set the stream to null after. If an exception is thrown before your stream = null statement, stream will be deleted when the usage block is displayed, and then again in your finally block.

Unfortunately, since you need to access your stream after document updated it, I don’t see a clean way to use my example setting stream = null in your using statement to avoid multiple Dispose() calls. An alternative would be that you could declare both stream and document outside the try block and then clear them at your end, for example:

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

A stream may still be deleted twice if an exception is thrown in the use block before the stream is zero. Try the following:

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

The using statement provides an object - so you call dispose twice

+2
source

Removing an object several times should always be safe. From the documentation for Dispose :

If the Dispose method object is called more than once, the object must ignore all calls after the first. An object should not throw an exception if its Dispose method is called multiple times.

Having said that, using an operator is definitely a way to go here. The only reason you got this method was because you explicitly deleted the object that you wouldn’t need, since the using statement should always place the object exactly once.

+2
source

When your code leaves the usage block around WordProcessingDocument , it will call dispose.

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

Because WordProcessingDocument accepts a stream instance in its constructor, it is called dispose on the stream instance when WordProcessingDocument.Dispose is WordProcessingDocument.Dispose . Then you enter the finally block, where you call stream.Dispose() - you called Dispose () twice on the stream instance.

0
source

All Articles