Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stream.Dispose or stream=null?

Tags:

c#

.net

I've have some code similar to this:

HttpWebRequest req;
HttpWebResponse response;
Stream receiveStream = null;
StreamReader readStream = null;
try
{
    req = (HttpWebRequest)WebRequest.Create("someUrl"));
    req.Credentials = CredentialCache.DefaultCredentials;

    req.Method = "GET";

    response = (HttpWebResponse)req.GetResponse();
    receiveStream = response.GetResponseStream();
    readStream = new StreamReader(receiveStream, Encoding.Default);

    return readStream.ReadToEnd();
}
catch
{
    return "Error";
}
finally 
{
    readStream = null;
    receiveStream = null;
    response = null;
    req = null;
}

Should this code have readStream.Dispose() and responseStream.Dispose() instead of setting both to null?

like image 755
Temple Avatar asked Aug 07 '09 15:08

Temple


People also ask

Should I dispose StreamReader?

Yes, StreamReader , StreamWriter , BinaryReader and BinaryWriter all close/dispose their underlying streams when you call Dispose on them. They don't dispose of the stream if the reader/writer is just garbage collected though - you should always dispose of the reader/writer, preferrably with a using statement.

Should I dispose MemoryStream?

You needn't call either Close or Dispose . MemoryStream doesn't hold any unmanaged resources, so the only resource to be reclaimed is memory. The memory will be reclaimed during garbage collection with the rest of the MemoryStream object when your code no longer references the MemoryStream .

Does dispose call close?

To do it right, you just need to know that Dispose() calls Close() (a pretty intimate piece of implementation trivia). Further, in the Dispose(bool) cases, you need to ignore Dispose() and just write a Dispose(bool) implementation that makes sure to chain the base class method.

Does StreamWriter dispose close the stream?

StreamWriter. Dispose() does close the underlying stream.


2 Answers

It's almost always a mistake to set local variables to null, unless you want to actually use that value later on. It doesn't force garbage collection any earlier - if you're not going to read from the variable later, the garbage collector can ignore the reference (when not in debug mode).

However, it's almost always correct to close streams - ideally in a using statement for simplicity.

It's also almost always wrong to have a bare "catch" block like that. Do you really want to handle anything going wrong, including things like OutOfMemoryException?

I would rewrite your code as:

HttpWebRequest req = (HttpWebRequest) WebRequest.Create("someUrl"));
req.Credentials = CredentialCache.DefaultCredentials;
req.Method = "GET";

using (WebResponse response = req.GetResponse())
{
    using (StreamReader reader = new StreamReader(response.GetResponseStream(),
                                                  Encoding.Default))
    {
        return reader.ReadToEnd();
    }
}

Now if something goes wrong, the exception will be propagated to the caller. You might want to catch a few specific exceptions, but it's generally not a good idea to represent errors using a value which could have been a valid "normal" response.

Finally, are you really sure you want Encoding.Default? That's the default encoding of the local machine - you normally want the encoding indicated by the response itself.

like image 152
Jon Skeet Avatar answered Nov 16 '22 00:11

Jon Skeet


It should have using [which calls Dispose()].

like image 41
Jimmy Avatar answered Nov 16 '22 00:11

Jimmy