Wednesday, April 13, 2011

How to implement dispose pattern with close method correctly (CA1063)

The Framework Design Guidelines (2nd Ed., page 327) say:

CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.

When doing so, it is important that you make the Close implementation identical to Dispose and consider implementing IDisposable.Dispose method explicitly.

So, following the provided example, I've got this class:

public class SomeClass : IDisposable {
    private SomeDisposable someInnerDisposable;

    public void Open() {
        this.someInnerDisposable = new SomeDisposable();
    }

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

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

    protected virtual void Dispose(bool disposing) {
        if (disposing) {
            this.someInnerDisposable.Dispose();
            this.someInnerDisposable = null;
        }
    }
}

FxCop doesn't seem to like that:

CA1816 : Microsoft.Usage : 'SomeClass.Close()' calls 'GC.SuppressFinalize(object)', a method that is typically only called within an implementation of 'IDisposable.Dispose'. Refer to the IDisposable pattern for more information.

CA1816 : Microsoft.Usage : Change 'SomeClass.IDisposable.Dispose()' to call 'GC.SuppressFinalize(object)'. This will prevent unnecessary finalization of the object once it has been disposed and it has fallen out of scope.

CA1063 : Microsoft.Design : Modify 'SomeClass.IDisposable.Dispose()' so that it calls Dispose(true), then calls GC.SuppressFinalize on the current object instance ('this' or 'Me' in Visual Basic), and then returns.

CA1063 : Microsoft.Design : Rename 'SomeClass.IDisposable.Dispose()' to 'Dispose' and ensure that it is declared as public and sealed.

  • How do I implement the dispose pattern with close method correctly?

-or-

  • How do I suppress the warnings?

I tried

[SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly",
    Justification = "Framework Design Guidelines say it's ok.")]
void IDisposable.Dispose()
{
    this.Close();
}

but FxCop 1.36 still reports them.

EDIT: Changing it around as suggested eliminates all but this warning:

CA1063 : Microsoft.Design : Rename 'SomeClass.IDisposable.Dispose()' to 'Dispose' and ensure that it is declared as public and sealed.

EDIT 2: CODE_ANALYSIS was indeed missing. Thanks.

From stackoverflow
  • Change it around.

    Have Close() call this.Dispose() and put the logic in the Dispose() method instead of the Close() method.

    ------------------- Further info after edit ---------------

    Also, changing the declaration to:

    public void Dispose()
    

    should get rid of the other error. Since you have it declared as:

    void IDisposable.Dispose()
    

    It's not marked as public and sealed, and FxCop complains. Personally, I prefer to get avoid the errors instead of suppressing them.

  • How do I suppress the warnings?

    SuppressMessage() only works when you specify the CODE_ANALYSIS flag as a conditional compilation symbol.

0 comments:

Post a Comment