Search code examples
c#.netmemory-leaksgarbage-collectiondispose

Is Dispose(bool) method necessary if a finalizer isn't implemented?


While Dispose Pattern is widely discussed on the Internet and SOF I could not find any resource that answer my questions.

Therefore, please be kind to read to the end before marking this as a duplicate. I will happily remove the question if you could point me to a previous question that I have missed.


I have seen many classes that (blindly?) implement dispose pattern without implementing a finalizer.

The MSDN article on Dispose Pattern says:

The Boolean parameter disposing indicates whether the method was invoked from the IDisposable.Dispose implementation or from the finalizer. The Dispose(bool) implementation should check the parameter before accessing other reference objects (e.g., the resource field in the preceding sample). Such objects should only be accessed when the method is called from the IDisposable.Dispose implementation (when the disposing parameter is equal to true). If the method is invoked from the finalizer (disposing is false), other objects should not be accessed. The reason is that objects are finalized in an unpredictable order and so they, or any of their dependencies, might already have been finalized.

According to what I understand GC calls the finalizer method (if implemented) which in turn should call the Dispose(bool) method with parameter as false.

My First question is if a class does not implement a finalizer then does the Dispose(bool) ever get called with parameter as false? (e.g. by something in the CLR that I haven't come across)

I understand Dispose(bool) can be used to make sure that objects are only disposed once.

Therefore, my second question is if a class does not need to implement a finalizer then can it simply implement the Dispose method like below?

private bool objectDisposed;
public void Dispose()
{
    if (!objectDisposed)
    {
        // Release/dispose managed resources
        // ...
        // ...

        objectDisposed = true;
    }
}

Solution

  • My First question is if a class does not implement a finalizer then does the Dispose(bool) ever get called with parameter as false? (e.g. by something in the CLR that I haven't come across)

    NO

    Therefore, my second question is if a class does not need to implement a finalizer then can it simply implement the Dispose method like below?

    I wouldn't, but you could. If you do, you will be reinventing the IDisposable pattern, if this class is going to be extended. As HansPassant indicated in the comment, IDisposable patterns comes very handy if there are derived classes. I would rather follow the pattern at the first place.

    Base class

    using System;
    
    class BaseClass : IDisposable
    {
       // Flag: Has Dispose already been called?
       bool disposed = false;
    
       // Public implementation of Dispose pattern callable by consumers.
       public void Dispose()
       { 
          Dispose(true);
          GC.SuppressFinalize(this);           
       }
    
       // Protected implementation of Dispose pattern.
       protected virtual void Dispose(bool disposing)
       {
          if (disposed)
             return; 
    
          if (disposing) {
             // Free any other managed objects here.
             //
          }
    
          // Free any unmanaged objects here.
          //
          disposed = true;
       }
    
       // Only if there are unmanaged resources.
       ~BaseClass()
       {
          Dispose(false);
       }
    }
    

    Derived Class

    using System;
    
    class DerivedClass : BaseClass
    {
       // Flag: Has Dispose already been called?
       bool disposed = false;
    
       // Protected implementation of Dispose pattern.
       protected override void Dispose(bool disposing)
       {
          if (disposed)
             return; 
    
          if (disposing) {
             // Free any other managed objects here.
             //
          }
    
          // Free any unmanaged objects here.
          //
          disposed = true;
    
          // Call the base class implementation.
          base.Dispose(disposing);
       }
    
       // Only if there are unmanaged resources.
       ~DerivedClass()
       {
          Dispose(false);
       }
    }