Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

fxcop

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.

like image 680
dtb Avatar asked Mar 10 '09 16:03

dtb


People also ask

How do you implement a Dispose method?

Implement the dispose pattern for a derived class Instead, to clean up a derived class, you provide the following: A protected override void Dispose(bool) method that overrides the base class method and performs the actual cleanup of the derived class. This method must also call the base. Dispose(bool) ( MyBase.

What is the best way to ensure an object implementing IDisposable is disposed?

If the class inherits from a class that implements IDisposable it must call the Dispose(), or Dispose(bool) method of the base class from within its own implementation of Dispose() or Dispose(bool), respectively. This ensures that all resources from the base class are properly released.

Why should one call GC SuppressFinalize when implementing Dispose method?

Dispose should call GC. SuppressFinalize so the garbage collector doesn't call the finalizer of the object. To prevent derived types with finalizers from having to reimplement IDisposable and to call it, unsealed types without finalizers should still call GC.

How do I call a Dispose method?

public void Dispose() { Dispose(disposing: true); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC. SuppressFinalize to // take this object off the finalization queue // and prevent finalization code for this object // from executing a second time.


1 Answers

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.

like image 146
Reed Copsey Avatar answered Sep 29 '22 03:09

Reed Copsey