Skip to content

Gendarme.Rules.Design.UseCorrectDisposeSignaturesRule(2.10)

Sebastien Pouliot edited this page Jan 22, 2011 · 2 revisions

UseCorrectDisposeSignaturesRule

Assembly: Gendarme.Rules.Design
Version: 2.10

Description

There is a convention that should be followed when implementing IDisposable. Part of this convention is that Dispose methods should have specific signatures. In particular an IDisposable type's Dispose methods should either be nullary or unary with a bool argument, Dispose () should not be virtual, Dispose (bool) should not be public, and unsealed types should have a protected virtual Dispose (bool) method. For more details see: [http://www.bluebytesoftware.com/blog/2005/04/08/DGUpdateDisposeFinalizationAndResourceManagement.aspx].

Examples

Bad example:

public class Unsealed : IDisposable
{
    ~Unsealed ()
    {
        Dispose (false);
    }
    public void Dispose ()
    {
        Dispose (true);
        GC.SuppressFinalize (this);
    }
    // This is not virtual so resources in derived classes cannot be
    // cleaned up in a timely fashion if Unsealed.Dispose () is called.
    protected void Dispose (bool disposing)
    {
        if (!Disposed) {
            // clean up my resources
            Disposed = true;
        }
    }
    protected bool Disposed {
        get;
        set;
    }
}

Good example:

public class Unsealed : IDisposable
{
    // Unsealed classes should have a finalizer even if they do nothing
    // in the Dispose (false) case to ensure derived classes are cleaned
    // up properly.
    ~Unsealed ()
    {
        Dispose (false);
    }
    public Unsealed ()
    {
    }
    public void Work ()
    {
        // In general all public methods should throw ObjectDisposedException
        // if Dispose has been called.
        if (Disposed) {
            throw new ObjectDisposedException (GetType ().Name);
        }
    }
    public void Dispose ()
    {
        Dispose (true);
        GC.SuppressFinalize (this);
    }
    protected virtual void Dispose (bool disposing)
    {
        // Multiple Dispose calls should be OK.
        if (!Disposed) {
            if (disposing) {
                // None of our fields have been finalized so it's safe to
                // clean them up here.
            }
            // Our fields may have been finalized so we should only
            // touch native fields (e.g. IntPtr or UIntPtr fields) here.
            Disposed = true;
        }
    }
    protected bool Disposed {
        get;
        private set;
    }
}

Notes

  • This rule is available since Gendarme 2.6
Clone this wiki locally