Question

I use a default IDisposable implementation template (pattern) for my code.

snippet:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

My question: why is the call "GC.SuppressFinalize(this)" in the Dispose public method? I would place "GC.SuppressFinalize(this)" in the "if (isDisposing)" section of the protected method, after disposing managed resources.

Like this:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
Was it helpful?

Solution

I suppose its a clear case of Template Design pattern.

Your abstract class is Designed to take care of all important/necessary tasks required (Here, GC.SuppressFinalize(this)), and allowing a derived class to override only some part of the code.

There are 2 cases here:
Snippet 1, SuppressFinalize, in Dispose
Snippet 2, SuppressFinalize, in Dispose(true)

Here, Snippet 1, makes sure that GC.SuppressFinalize is always executed. While snippet 2, leaves the execution of GC.SuppressFinalize at the mercy of derived class.

So, by putting GC.SuppressFinalize, in Dispose method, you as a designer of your class will always make sure that irrespective of whatever code written by derived classes, GC.SuppressFinalize will be executed.

This is only the benefit of writing SuppressFinalize in Dispose rather then Dispose(true).

OTHER TIPS

The Dispose(bool isDisposing) method isn't part of the IDisposable interface.

You would normally call Dispose(true) from your Dispose method, and call Dispose(false) from your finalizer, as a fallback in the case where the object hasn't already been disposed.

Calling SuppressFinalize tells the GC that there's no need to call your object's finalizer, presumably because all your cleanup was done when Dispose was called.

If you don't have a finalizer on your class, then you don't need to call SuppressFinalize at all, since there's no finalizer to suppress!

Joe Duffy has some great guidelines on disposal, finalization, garbage collection etc.

I think either layout could have been chosen, but probably they wanted to emphasize "put all deallocation code in this method" in the protected Dispose method, so they put the other artifact of disposing (Suppressing finalization) elsewhere.

Also, suppose a derived class had another reason for calling the protected Dispose method, but did still want finalization to occur (for whatever imagined reason, I don't know).

Cause .Dispose is when managed code (your code) disposes of the object thereby opting out of finalisation. People usually create another route into Dispose(bool disposing) via a finaliser and the call wouldn't make any sense for the finaliser to make.

The idea is that your cleanup code should only be called once. However there are two points of entry: the Dispose method and object finalizers. When Dispose is called, you opt-out of finalization so that your cleanup code is only called once. The code here might illustrate it better.

Quote:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top