5

Why is it that a nested using block will dispose an object multiple times?

In reference to CA2202:

In the following example, a Stream object that is created in an outer using statement is released at the end of the inner using statement in the Dispose method of the StreamWriter object that contains the stream object. At the end of the outer using statement, the stream object is released a second time. The second release is a violation of CA2202.

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

I know that in most cases I can use

using ()
using ()
{ }

And when I cannot I am happy to revert to try finally like it suggests, I would just like to know why it works with way.

Is it just the best way the generated code can be interpreted, "Okay, as using block is closing, let me dispose all objects." or is there a reason for it working this way?

JonathanPeel
  • 743
  • 1
  • 7
  • 19

2 Answers2

11

The using block itself won't dispose of anything more than once.

The "problem" (and it does really need the quotes because it's only a problem in the most abstract mathematical sense) is that in this specific scenario the StreamWriter takes ownership of the underlying stream, so when the writer is disposed by the inner using it automatically disposes of the stream as well. Then the outer using goes on to dispose of the stream again.

This is not a problem in practice because Stream can be safely disposed of multiple times. If you have to have total correctness you can still make the stream be disposed of only once by using the appropriate StreamWriter constructor that causes the writer to not take ownership of the stream.

Jon
  • 428,835
  • 81
  • 738
  • 806
6

Disposing a StreamWriter also disposed the underlying stream. You can configure StreamWriter to not do that.

Subjective note: That said this warning is bogus and unhelpful because disposing objects multiple time is generally safe (if those objects adhere to the common dispose pattern. All BCL objects can be disposed of safely multiple times).

usr
  • 168,620
  • 35
  • 240
  • 369
  • Yes, part of the implementation guidelines for `IDisposable` is that it should be tolerant of multiple calls. – Adam Houldsworth Jul 11 '14 at 14:03
  • How do you configure `Streamwriter` not to do that then? – Chris Jul 11 '14 at 14:05
  • 1
    @Chris there's a constructor argument for that. I don't recommend using that if not necessary. Here, it's not necessary. The warning is just pedantic garbage. Doesn't help anyone get their work done. – usr Jul 11 '14 at 14:06
  • Ah cool. I did wonder. I just thought that if you were going to mention that you can configure it that it would be worth saying how to as well. – Chris Jul 11 '14 at 14:07