Does Disposing Streamreader Close the Stream

Does disposing streamreader close the stream?

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. (In fact, none of these classes have finalizers, nor should they have.)

Personally I prefer to have a using statement for the stream as well. You can nest using statements without braces quite neatly:

using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}

Even though the using statement for the stream is somewhat redundant (unless the StreamReader constructor throws an exception) I consider it best practice as then if you get rid of the StreamReader and just use the stream directly at a later date, you'll already have the right disposal semantics.

Does .Disposing a StreamWriter close the underlying stream?

StreamWriter.Close() just calls StreamWriter.Dispose() under the bonnet, so they do exactly the same thing.
StreamWriter.Dispose() does close the underlying stream.

Reflector is your friend for questions like this :)

Should I call Close() or Dispose() for stream objects?

A quick jump into Reflector.NET shows that the Close() method on StreamWriter is:

public override void Close()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

And StreamReader is:

public override void Close()
{
this.Dispose(true);
}

The Dispose(bool disposing) override in StreamReader is:

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;
/* deleted for brevity */
base.Dispose(disposing);
}
}
}

The StreamWriter method is similar.

So, reading the code it is clear that that you can call Close() & Dispose() on streams as often as you like and in any order. It won't change the behaviour in any way.

So it comes down to whether or not it is more readable to use Dispose(), Close() and/or using ( ... ) { ... }.

My personal preference is that using ( ... ) { ... } should always be used when possible as it helps you to "not run with scissors".

But, while this helps correctness, it does reduce readability. In C# we already have plethora of closing curly braces so how do we know which one actually performs the close on the stream?

So I think it is best to do this:

using (var stream = ...)
{
/* code */

stream.Close();
}

It doesn't affect the behaviour of the code, but it does aid readability.

Disposing a StreamReader that read a stream that is defined out of scope?

You could invert control using a closure. That is, create a method like so:

// This method will open the stream, execute the streamClosure, and then close the stream.
public static String StreamWork(Func<Stream, String> streamClosure) {
// Set up the stream here.
using (Stream stream = new MemoryStream()) { // Pretend the MemoryStream is your actual stream.

// Execute the closure. Return it's results.
return streamClosure(stream);
}
}

which is responsible for opening / closing the stream within the method.

Then you simply wrap up all the code that needs the stream into a Func<Stream, String> closure, and pass it in. The StreamWork method will open the stream, execute your code, then close the stream.

public static void Main()
{
// Wrap all of the work that needs to be done in a closure.
// This represents all the work that needs to be done while the stream is open.
Func<Stream, String> streamClosure = delegate(Stream stream) {
using (StreamReader streamReader = new StreamReader(stream)) {
return streamReader.ReadToEnd();
}
};

// Call StreamWork. This method handles creating/closing the stream.
String result = StreamWork(streamClosure);
Console.WriteLine(result);
Console.ReadLine();
}

UPDATE

Of course, this method of inversion is a matter of preference as mentioned in the comments below. The key point is to ensure that the stream is closed rather than allowing it to float around until the GC cleans it up (since the whole point of having stuff implement IDisposable is to avoid that sort of situation to begin with). Since this is a library function that accepts a Stream as input, the assumption is that the method-consumer will be creating the stream, and therefore as you point out, has the responsibility of ultimately closing the stream as well. But for sensitive resources where you are concerned about ensuring clean up occurs absolutely, inversion is sometimes a useful technique.

Is there a benefit in closing StreamReader (or StreamWriter) when I close Stream explicitly?

You do need to close a StreamWriter (generally via the using block), or else data in its buffer could be lost.

Because both StreamReader and StreamWriter default to closing the stream automatically, if you want to eliminate one using block from your code, it should be the Stream that you remove from using.

If you can't do that, for example you've borrowed the Stream from elsewhere that doesn't want you to close it, then you must use the leaveOpen parameter you're already aware of. The reason that you can't just omit the using statement for a StreamReader/StreamWriter in order to leave it open, is that the garbage collector will still trigger some cleanup (although not as much) since the object is unreachable... only this will now occur at an unrelated time, creating an unpredictable bug that's very hard to find.

It is indeed ugly that you can't specify leaveOpen without explicitly controlling the buffer size, etc. May I suggest a helper method along the lines of StreamReader CreateStreamReaderLeaveOpen(Stream)?

Will closing a FileStream close the StreamReader?

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);
}
}
}
}

Leave StreamReader without closing Stream

There is an overload of the StreamReader constructor which accepts a bool leaveOpen parameter. Passing true prevents the StreamReader from closing the stream when the StreamReader is disposed.

leaveOpen

Type: System.Boolean

true to leave the stream open after the StreamReader object is disposed; otherwise, false.

Example, using the default UTF8 encoding and 1024-byte buffer that you get with the simpler StreamReader constructors:

using (var reader = new StreamReader(stream, Encoding.UTF8, true, 1024, true))
{
// use reader
} // stream will NOT be closed here

Can you keep a StreamReader from disposing the underlying stream?


I don't want to just let it go out of scope, either. Then the garbage collector will eventually call the Dispose, killing the stream.

Garbage collector will call the Finalize method (destructor), not the Dispose method. The finalizer will call Dispose(false) which will not dispose the underlying stream. You should be OK by leaving the StreamReader go out of scope if you need to use the underlying stream directly. Just make sure you dispose the underlying stream manually when it's appropriate.

Why disposing StreamReader makes a stream unreadable?

This happens because the StreamReader takes over 'ownership' of the stream. In other words, it makes itself responsible for closing the source stream. As soon as your program calls Dispose or Close (leaving the using statement scope in your case) then it will dispose the source stream as well. Calling fs.Dispose() in your case. So the file stream is dead after leaving the first using block. It is consistent behavior, all stream classes in .NET that wrap another stream behave this way.

There is one constructor for StreamReader that allows saying that it doesn't own the source stream. It is however not accessible from a .NET program, the constructor is internal.

In this particular case, you'd solve the problem by not using the using-statement for the StreamReader. That's however a fairly hairy implementation detail. There's surely a better solution available to you but the code is too synthetic to propose a real one.

Does Stream.Dispose always call Stream.Close (and Stream.Flush)


Can I just call MySW.Dispose() and
skip the Close even though it is
provided?

Yes, that’s what it’s for.

Are there any Stream implementations
that don't work as expected (Like
CryptoStream)?

It is safe to assume that if an object implements IDisposable, it will dispose of itself properly.

If it doesn’t, then that would be a bug.

If not, then is the following just bad
code:

No, that code is the recommended way of dealing with objects that implement IDisposable.

More excellent information is in the accepted answer to Close and Dispose - which to call?



Related Topics



Leave a reply



Submit