Search code examples
c#.netgarbage-collectionidisposablesuppressfinalize

What's the purpose of GC.SuppressFinalize(this) in Dispose() method?


I have the following code:

public void Dispose()
{
    if (_instance != null)
    {
        _instance = null;
        // Call GC.SupressFinalize to take this object off the finalization
        // queue and prevent finalization code for this object from
        // executing a second time.
        GC.SuppressFinalize(this);
    }
}

Although there is a comment that explains purpose of that GC-related call, I still don't understand why it's there.

Isn't object destined for garbage collection once all instances cease from existence, like, when used in using block?

What's the use case scenario where this would play important role?


Solution

  • When implementing the dispose pattern you might also add a finalizer to your class that calls Dispose(). This is to make sure that Dispose() always gets called, even if a client forgets to call it.

    To prevent the dispose method from running twice (in case the object already has been disposed) you add GC.SuppressFinalize(this);. The documentation provides a sample:

    class MyResource : IDisposable
    {
        [...]
    
        // This destructor will run only if the Dispose method 
        // does not get called.
        ~MyResource()      
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
    
        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue 
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }
    
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources.
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }
    
                // Call the appropriate methods to clean up 
                // unmanaged resources here.
                resource.Cleanup()          
            }
            disposed = true;         
        }
    }