Jonathan Wood
Jonathan Wood

Reputation: 67335

Using Disposable Pattern to Clean Up IDispose Member Classes

Part of the disposable pattern includes the following method.

protected virtual void Dispose(bool disposing)
{
    if (!disposed)
    {
        if (disposing)
        {
            // TODO: dispose managed state (managed objects).
        }

        // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
        // TODO: set large fields to null.
        disposed = true;
    }
}

This method has different handling to clean up managed and unmanaged resources. But what if I want to clean up a class member that implements IDisposable?

Normally, I don't know if that member cleans up managed or unmanaged resources. So if I want my Dispose method to clean up a class member that implements IDisposable, would I call Dispose() on that member in the managed or unmanaged sections in the code above?

Upvotes: 3

Views: 1353

Answers (2)

rexcfnghk
rexcfnghk

Reputation: 15502

The standard way of disposing class members that implements IDisposable is like this:

public class Foo : IDisposable
{
    // MemoryStream implements IDisposable
    private readonly Stream _stream = new MemoryStream();

    private bool _disposed;

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

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
        {
            return;
        }

        if (disposing)
        {
            _stream.Dispose();
        }

        _disposed = true;
    }
}

To clarify, cleaning up managed resources means the resource itself implements IDisposable (as MemoryStream does above). MemoryStream/Stream holds the underlying unmanaged resource and its cleanup logic is implemented for you already. There is no need to clean up unmanaged resources in Foo.

Upvotes: 1

Frank Boyne
Frank Boyne

Reputation: 4570

You should call Dispose in the managed section (i.e., only when disposing is true).

Part of the guidance in Dispose Pattern under Framework Design Guidelines is:

The Boolean parameter disposing indicates whether the method was invoked from the IDisposable.Dispose implementation or from the finalizer. The Dispose(bool) implementation should check the parameter before accessing other reference objects [...]. Such objects should only be accessed when the method is called from the IDisposable.Dispose implementation (when the disposing parameter is equal to true). If the method is invoked from the finalizer (disposing is false), other objects should not be accessed. The reason is that objects are finalized in an unpredictable order and so they, or any of their dependencies, might already have been finalized.

Another useful resource is Implementing a Dispose Method

Upvotes: 3

Related Questions