3

In documentation from Microsoft the following example is given for using streams.

Stream stream = null;  
try  
{  
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);  
    using (StreamWriter writer = new StreamWriter(stream))  
    {  
        stream = null;  
        // Use the writer object...  
    }  
}  
finally  
{  
    if(stream != null)  
        stream.Dispose();  
}  

Now i was wondering why would you set the stream = null before using the writer object?

mschuurmans
  • 1,088
  • 1
  • 12
  • 24
  • To be able to use the variable in the finally section, I reckon. You have to define it outside the try block to use that way. __EDIT__ wrong alarm, the question does not refer to the very first line. – vahdet May 31 '18 at 11:18
  • Probably for disposing and memory leaking of the stream. Normally you wrap the FileStream also in an using block – Jordy van Eijk May 31 '18 at 11:19
  • @vahdet that's not the question. He's talking about the line right over the comment, inside the `using` part – Rafalon May 31 '18 at 11:19
  • @JordyvanEijk While it should always be legal, they are trying to not double-dispose the `stream`. `StreamWriter` will already dispose it on closing. – xanatos May 31 '18 at 11:20
  • 1
    But double-disposing it won't be a problem so it's unnecessary. Changing the outer try/finally to a using-block would be better though. – Lasse V. Karlsen May 31 '18 at 11:22
  • 2
    I would really suggest reading [this Q&A](https://stackoverflow.com/questions/28445790/how-to-satisfy-ca2202-do-not-dispose-objects-multiple-times). Just ignore the warning, it is useless – Camilo Terevinto May 31 '18 at 11:23

1 Answers1

3

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.

xanatos
  • 109,618
  • 12
  • 197
  • 280