Should I Call Close() or Dispose() for Stream Objects

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.

Who should dispose a Stream? The called method or the caller?

The caller should be responsible for the resources. The called method has no information (neither should it have any) whether the provided object will be used by others. So it's a bad decision to dispose any objects provided to a method (e.g. what if this object's lifetime is managed by a Dependency Injection container?)

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?

Reasons to use Close over Dispose for a Stream?

Only in System.Windows.Forms.Form and System.Data.SqlClient.SQLConnectoin do Close and Dispose have different behavior. This has to do with dispose being hidden in situations where the behavior was not clear in context. This is more deeply explained here MSDN Difference Between Close and Dispose

MemoryStream.Close() or MemoryStream.Dispose()

Close() and Dispose(), when called on a MemoryStream, only serve to do two things:

  • Mark the object disposed so that future accidental usage of the object will throw an exception.
  • Possibly1 release references to managed objects, which can make the GC's job a bit easier depending on the GC implementation. (On today's GC algorithms it makes no real difference, so this is a point for an academic discussion and has no significant real-world impact.)

MemoryStream does not have any unmanaged resources to dispose, so you don't technically have to dispose of it. The effect of not disposing a MemoryStream is roughly the same thing as dropping a reference to a byte[] -- the GC will clean both up the same way.

Which one do I call? Is it necessary to call both?

The Dispose() method of streams delegate directly to the Close() method2, so both do exactly the same thing.

Will the other throw an exception if I have already called one of them?

The documentation for IDisposable.Dispose() specifically states it is safe to call Dispose() multiple times, on any object3. (If that is not true for a particular class then that class implements the IDisposable interface in a way that violates its contract, and this would be a bug.)

All that to say: it really doesn't make a huge difference whether you dispose a MemoryStream or not. The only real reason it has Close/Dispose methods is because it inherits from Stream, which requires those methods as part of its contract to support streams that do have unmanaged resources (such as file or socket descriptors).


1 Mono's implementation does not release the byte[] reference. I don't know if the Microsoft implementation does.

2 "This method calls Close, which then calls Stream.Dispose(Boolean)."

3 "If an object's Dispose method is called more than once, the object must ignore all calls after the first one."

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 :)

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)?

MemoryStream in Using Statement - Do I need to call close()

No, it's not.

using ensures that Dispose() will be called, which in turn calls the Close() method.

You can assume that all kinds of Streams are getting closed by the using statement.

From MSDN:

When you use an object that accesses unmanaged resources, such as a StreamWriter, a good practice is to create the instance with a using statement. The using statement automatically closes the stream and calls Dispose on the object when the code that is using it has completed.



Related Topics



Leave a reply



Submit