CS.IDISP.DTOR

Provide a destructor (finalizer) when you implement IDisposable.

This rule identifies code that does not implement a finalizer (destructor) in a class that implements the Idisposable interface. Some classes implement the Idisposable interface to let the users free the resources allocated by the class. However, users might forget to call the Dispose method. To code defensively, ensure that such classes also implement a finalizer (destructor in C#, managed C++). This way, even if the user forgets to call the Dispose method, the resources get freed when the garbage collector calls the finalizer.

Vulnerability and risk

Not implementing standard design pattern will increase the risk of memory mis-management.

Mitigation and prevention

Problem is fixed by implementing Idisposable interface and calling Dispose() from the destructor.

Vulnerable code example

Copy
  using System;
  public class A : Idisposable
  {
      private bool _alreadyDisposed = false;
      public A()
      {
          // resource allocated here
      }
      public virtual void Dispose()
     {
         Dispose(true);
     }
     public virtual void Dispose(bool isDisposing)
     {
         if (_alreadyDisposed)
         {
             return;
         }
         if (isDisposing)
         {
             // Free managed resources
         }
         // Free unmanaged resources
         _alreadyDisposed = true;
     }
     // VIOLATION: Does not implement the destructor.
     // However, Idisposable interface is implemented.
 }

Fixed code example

Copy
  // Problem is fixed by implementing Idisposable interface
  // and calling Dispose() from the destructor.
  Using System;
  public class A : Idisposable
  {
      private bool _alreadyDisposed = false;
      public A()
      {
          // resource allocated here
     }
     // FIXED: Destructor implemented.
     // Also note the call to GC.SuppressFinalize().
     ~A()
     {
         // Dispose() called from the destructor
         Dispose(false);
     }
     public virtual void Dispose()
     {
         Dispose(true);
         GC.SuppressFinalize();
     }
     public virtual void Dispose(bool isDisposing)
     {
         if (_alreadyDisposed)
         {
             return;
         }
         if (isDisposing)
         {
             // Free managed resources
         }
         // Free unmanaged resources
         _alreadyDisposed = true;
     }
 }

REFERENCES: .NET Framework General Reference, Design Guidelines for Class Library Developers.