views:

626

answers:

5

If I use a FileStream to create a StreamReader, will the StreamReader close when I close the FileStream or will I need to close the StreamReader too?

public void ReadFile()
{
    var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read);
    var reader = new StreamReader(file);

    try
    {
     txtFile.Text = reader.ReadToEnd();
    }
    catch (Exception)
    {
     throw;
    }
    finally
    {
     file.Close();
    }
}
+3  A: 

Essentially yes. You don't actually have to close a StreamReader. If you do, all it does is closes the underlying stream.

@Bruno makes a good point about closing the outer-most wrapper. It is good practice to close the outer-most stream and let it close underlying streams in order to ensure all resources are released properly.

From Reflector...

public class StreamReader : TextReader
{
    public override void Close()
    {
        this.Dispose(true);
    }

    protected override void Dispose(bool disposing)
    {
        try
        {
            if ((this.Closable && disposing) && (this.stream != null))
            {
                this.stream.Close();
            }
        }
        finally
        {
            if (this.Closable && (this.stream != null))
            {
                this.stream = null;
                this.encoding = null;
                this.decoder = null;
                this.byteBuffer = null;
                this.charBuffer = null;
                this.charPos = 0;
                this.charLen = 0;
                base.Dispose(disposing);
            }
        }
    }
}
Brian
IMO, this is a really bad practice. In the future, BCL designers might opt to add some additional structures that need to be disposed...
bruno conde
@bruno conde: you yourself said that the top most wrapper should be disposed. StreamReader is the top wrapper for FileReader. Where is the problem?
Kamarey
@Kamarey, the problem is that the OP is only disposing of FileStream.
bruno conde
@bruno conde: Agree with you, the OP should close the StreamReader instead.
Kamarey
@Bruno, I agree with you that the outer-most stream should be closed. Even if it doesn't do anything interesting other than close the inner stream, it is a good idea for exactly the reason you state, forward compatibility. It is also good practice so that you don't forget to do it when working with other streams that do need to be closed.
Brian
A: 

No. The best thing to do is close them in reverse order that you opened them.

David Brunelle
+3  A: 

No. You should close the reader instead. In practice, this might not present any problem but, the StreamReader could add some overhead that might need to be cleaned. So you should always close the top most wrapper.

bruno conde
+1  A: 

You don't need to close the StreamReader because it doesn't own any unmanaged resources. Closing the FileStream is sufficient. You can rewrite your code with using like this:

public void ReadFile()
{
    using (var file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
    {
        txtFile.Text = new StreamReader(file).ReadToEnd();
    }
}

In general if you are in doubt it is best to be safe and Dispose all IDisposable objects when you have finished using them.

public void ReadFile()
{
    using (FileStream file = new FileStream("c:\file.txt", FileMode.Open, FileAccess.Read))
    {
        using (StreamReader streamReader = new StreamReader(file))
        {
            txtFile.Text = streamReader.ReadToEnd();
        }
    }
}
Mark Byers
The "using" I know disposes of the object, does this ensure that the connection is close as well?
norlando02
+5  A: 

You could also just use the File.ReadAllText method:

txtFile.Text = File.ReadAllText(@"c:\file.txt");
Tommy Carlier
How does that work? Does it just open a connection, read the entire file, then close the file?
norlando02
Yes, it does exactly that.
Tommy Carlier