GC.SuppressFinalize method to suppress the finalizer

By Indranil Chatterjee

We often have cleanup code (especially for unmanaged resources) written in IDisposable.Dispose method as well as a finalizer method. Objects implementing IDisposable interface can suppress the finalizer method call for it if it is not required.

Cleanup code (especially for unmanaged resources can be written by implementing IDisposable.Dispose method or in a finalizer (often its recommended to do both as one can't be sure which gets called earlier). However, whenever a garbage collector observes a finalizer method during a garbage collection pass, it places the object on a finalizer queue (which is polled by a separate thread to invoke finalizers on objects lying there) and skips the collection.

So, one can say that finalizers delay the garbage collection by at least one pass. If Dispose gets called earlier (either explicitly or as a part of a using block), one can avoid re-running the same cleanup in finalizer (moreover, it can cause error if one tries to cleanup something which has already been cleaned up). This can be done by calling GC.SuppressFinalize method.

The call GC.SuppressFinalize(this) instructs the garbage collector not call the finalizer for the current object. It's generally invoked from the implementation of IDisposable.Dispose method.

Here is a sample code demonstrating the use of SuppressFinalize in a dispose pattern:

using System;

namespace ConsoleApplication1
{    
    
//This class can be used as a base class to wrap resources
    
//that require cleanup
    
public class MySafeResource : IDisposable
    {
        
//Private flag that tracks if the stream has been disposed
        
private bool _disposed;
        
//Fields that require cleanup
        

         
public MySafeResource()
        {
            
//Initialize resources (that require cleanup) here
        }

         
public void Dispose()
        {
             
//Dispose resources
          
Dispose(true);
            
//Suppress the finalizer call in case dispose gets called earlier.
            
//This prevents the garbage collector from putting this object on
            
//finalizer queue
          
GC.SuppressFinalize(this);
        }

         
//Derived classes just need to override this method to provide their
        
//cleanup logic
        
protected virtual void Dispose(bool disposing)
        {
             
//Check if the strem is not already disposed
            
if (!_disposed)
             {
                 
if (disposing)
                 {
                     
//Dispose only, non-finalizer logic
                 }                     

                  
//Place common cleanup logic to run for both Dispose and
                 
//finalizer

                 
//Set the fields to indicate that the resources has been
                 
//disposed
                _disposed =
true;
            }             
        }

         ~MySafeResource()
         {
             
//Call Dispose with false to ensure only common cleanup logic
            
//runs
          
Dispose(false);
        }
     }
}

GC.SuppressFinalize method to suppress the finalizer  (1265 Views)