Search code examples
c#design-patternsidisposable

Implementing C# IDisposable


I am trying to work out exactly what I need to do to dispose of a property in C# when using IDisposable. I can see the template, but I am not sure about actually disposing of objects.

I am working with the example given on this site: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose

I have added 3 properties:

privInt: Private value type. Would I dispose of this as it could be saved on the heap so may require GC? If I would then how, cannot set to null or call dispose? If not then I assume it has to be left to GC - but is it not the point of Dispose to free resources?

NonIDisClassInstance - Do I set to null? Is that enough

Can anyone comment on my implementation below and advise on what is correct/wrong.

IDisClass - Just call dispose

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);           
   }

   //Private value type
   private int privInt;

   //Private class that does not implement IDisposable
   Private NonIDisClass NonIDisClassInstance;

   //Private class that does implement IDisposable
   Private IDisClass IDisClassInstance;

   // 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.     
      DisposeOfThis = ????;
      NonIDisClassInstance = null;
      IDisClassInstance.Dispose();
      disposed = true;
   }

   ~BaseClass()
   {
      Dispose(false);
   }
}

Solution

    • You only need GC.SuppressFinalize(this); and a destructor if you are working with unmanaged memory. If not you can safely omit this.
    • In your Dispose implementation call this.IDisClassInstance?.Dispose();, that is all you need.

    Your code can be condensed down to this.

    class BaseClass : System.IDisposable
    {
    
        public virtual void Dispose()
        {
            // never throw an exception from Dispose so prevent an NRE by using ?.
            this.IDisClassInstance?.Dispose();
        }
    
        //Private class that does not implement IDisposable
        private object NonIDisClassInstance;
    
        //Private class that does implement IDisposable
        private IDisposable IDisClassInstance;
    }
    

    Do keep in mind that using Dispose is not necessarily about freeing up memory, it is about cleaning up / freeing up unmanaged resources which might also include memory. Things like open file streams or database connections or network connections.

    Note that your derived types can override Dispose but those overriden methods should include a call to base.Dispose(); so the managed resources of the base class are released.