The CA2202 is titled Do not dispose objects multiple time. I think that it is a stupid rule, because the description of IDisposable.Dispose() is very clear on this:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times.
so it is a rule about a non-problem, that causes the code to be more complex, for nothing! (note that I'm not the only and only one that things this).
Basic information: the StreamWriter
class will normally Close()
(that is equivalent to Dispose()
for Stream
classes) on Close()
/Dispose()
, and it is said to take ownership of the base stream.
The basic problem is that the normal code
using (stream = new FileStream("file.txt", FileMode.OpenOrCreate))
using (StreamWriter writer = new StreamWriter(stream))
{
}
will double Close()
the stream
(once from the StreamWriter
, once from the external using
), and this is frowned by the rule.
So we want to "manually" handle the Dispose()
of the stream
if StreamWriter
hasn't taken ownership of the stream
.
Now... "normal" exceptions can be thrown by the FileStream
constructor (and in this case stream
will be null
, so nothing to clear), or in the StreamWriter
constructor (and in this case stream
will be not-null
and writer
will be null
, so stream
will need disposing, done in the finally
block). Only asynchronous exceptions can be thrown between the end of the StreamWriter
construction and the stream = null;
but we will ignore them. Now... After the StreamWriter
has been constructed and assigned to writer
, stream
can be marked as "we don't need to dispose it" (because the StreamWriter
will close it for us), so stream = null;
. Note that putting other lines between the using ()
and the stream = null;
could create other points where an exception is thrown, like:
using (StreamWriter writer = new StreamWriter(stream))
{
if (something)
throw new Exception();
stream = null;
// Use the writer object...
}
but this would cause a double Dispose()
on the FileStream
.