tags:

views:

4633

answers:

4

In .NET, under which circumstances should I use GC.SuppressFinalize()?

What advantage(s) does using this method give me?

+1  A: 

That method must be called on the Dispose method of objects that implements the IDisposable, in this way the GC wouldn't call the finalizer another time if someones calls the Dispose method.

See: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

AlbertEin
I think "Must" is wrong - not even "should" - It's just that in some scenarios, you can eliminate the overhead of queueing/finalizing the object.
Basiclife
+5  A: 

you're telling the system that whatever work would have been done in the finalizer has already been done, so the finalizer doesn't need to be called. From the .NET docs:

Objects that implement the IDisposable interface can call this method from the IDisposable.Dispose method to prevent the garbage collector from calling Object.Finalize on an object that does not require it.

In general, most any Dispose() method should be able to call GC.SupressFinalize(), because it should clean up everything that would be cleand up in the finalizer.

SupressFinalize is just something that provides an optimization that allows the system to not bother queing the object to the finalizer thread. A properly written Dispose()/finalizer should work properly with or without a call to GC.SupressFinalize().

Michael Burr
+2  A: 

Generally when implementing the IDisposable pattern when you do not need to finalize your object. Check out http://www.blackwasp.co.uk/IDisposable.aspx for examples.

BlackWasp
+11  A: 

SuppresFinalize should only be called by a class that has a finalizer. It's informing the GC that this object was cleaned up fully.

The recommended IDisposable pattern when you have a finalizer is....

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }

            disposed = true;
        }
    }

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

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

Normally, the CLR keeps tabs on objects with a finalizer when they are created (making them more expensive to create). SuppressFinalize tells the garbage collector (GC) that the object was cleaned up properly and doesn't need to go onto the the finalizer queue. It looks like a C++ destructor, but it doesn't act anything like one.

The SuppressFinalize optimization is not trivial, as your objects can live a long time waiting on the finalizer queue. Don't be tempted to call SuppressFinalize on other objects mind you. That's a serious defect waiting to happen.

Design guidelines inform us that a finalizer isn't necessary if your object implements IDisposable, but if you have a finalizer you should implement IDisposable to allow deterministic cleanup of your class.

Most of the time you should be able to get away with IDisposable to clean up resources. You should only need a finalizer when your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up.

Note: Sometimes coders will add a finalizer to debug builds of their own IDisposable classes in order to test that code has disposed their IDisposable object properly.

    public void Dispose() // Implement IDisposable
    {
        Dispose(true);
    #if DEBUG
        GC.SuppressFinalize(this);
    #endif
    }

    #if DEBUG
    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
    #endif
Robert Paulson
I agree with your code but I would put an assert into the debug version...and if the resource being disposed was expensive, I would leave the finalizer in the release verion.
Jack Bolding
In the first code snippet I'm just posting what the recommended IDisposable + finalizer pattern looks like. Debugging code is good, but it can be distracting. .. I can only recommend avoiding finalizers except for classes that have unmanaged resources. Writing safe finalizer code is non-trivial.
Robert Paulson
Can I use disposing pattern in a base class and extend it among others one?
Eduardo Xavier
@Eduardo, yes you can absolutely. The recommended Dispose method is `protected virtual` for this reason, and follows what is called the NVPI pattern (Non Virtual Public Interface). Just make sure you document how subclasses should implement IDisposable and you're set.
Robert Paulson