[ACCEPTED]-Does Stream.Dispose always call Stream.Close (and Stream.Flush)-using

Accepted answer
Score: 83

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

Yes, that’s 9 what it’s for.

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

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

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

If 4 not, then is the following just bad code:

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

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

Score: 59

I used Reflector and found that System.IO.Stream.Dispose looks like 1 this:

public void Dispose()
{
    this.Close();
}
Score: 22

As Daniel Bruckner mentioned, Dispose and 8 Close are effectively the same thing.

However 7 Stream does NOT call Flush() when it is 6 disposed/closed. FileStream (and I assume 5 any other Stream with a caching mechanism) does 4 call Flush() when disposed.

If you are 3 extending Stream, or MemoryStream etc. you 2 will need to implement a call to Flush() when 1 disposed/closed if it is necessary.

Score: 4

All standard Streams (FileStream, CryptoStream) will 10 attempt to flush when closed/disposed. I 9 think you can rely on this for any Microsoft 8 stream implementations.

As a result, Close/Dispose 7 can throw an exception if the flush fails.

In 6 fact IIRC there was a bug in the .NET 1.0 5 implementation of FileStream in that it 4 would fail to release the file handle if 3 the flush throws an exception. This was 2 fixed in .NET 1.1 by adding a try/finally 1 block to the Dispose(boolean) method.

Score: 3

Both StreamWriter.Dispose() and Stream.Dispose() release 8 all resources held by the objects. Both 7 of them close the underlying stream.

The 6 source code of Stream.Dispose() (note that 5 this is implementation details so don't 4 rely on it):

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

StreamWriter.Dispose() (same 3 as with Stream.Dispose()):

protected override void Dispose(bool disposing)
{
    try
    {
        // Not relevant things
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            try
            {
                if (disposing)
                {
                    this.stream.Close();
                }
            }
            finally
            {
                // Not relevant things
            }
        }
    }
}

Still, I usually 2 implicitly close streams/streamwriters before 1 disposing them - I think it looks cleaner.

Score: 3

For objects that need to be manually closed, every 5 effort should be made to create the object 4 in a using block.

//Cannot access 'stream'
using (FileStream stream = File.Open ("c:\\test.bin"))
{
   //Do work on 'stream'
} // 'stream' is closed and disposed of even if there is an exception escaping this block
// Cannot access 'stream' 

In this way one can never 3 incorrectly access 'stream' out of the context 2 of the using clause and the file is always 1 closed.

Score: 3

I looked in the .net source for the Stream 2 class, it had the following which would 1 suggest that yes you can...

    // Stream used to require that all cleanup logic went into Close(),
    // which was thought up before we invented IDisposable.  However, we 
    // need to follow the IDisposable pattern so that users can write
    // sensible subclasses without needing to inspect all their base
    // classes, and without worrying about version brittleness, from a
    // base class switching to the Dispose pattern.  We're moving 
    // Stream to the Dispose(bool) pattern - that's where all subclasses
    // should put their cleanup starting in V2. 
    public virtual void Close() 
    {
        Dispose(true); 
        GC.SuppressFinalize(this);
    }

    public void Dispose() 
    {
        Close(); 
    } 
Score: 2

Stream.Close is implemented by a call to Stream.Dispose or vice versa 7 - so the methods are equivalent. Stream.Close exists 6 just because closing a stream sounds more 5 natural than disposing a stream.

Besides 4 you should try to avoid explicit calls to 3 this methods and use the using statement instead 2 in order to get correct exception handling 1 for free.

More Related questions