CS.IDISP.DISPOSE

Implement Dispose(bool) as a virtual method if IDisposable is implemented.

The standard design pattern to implement IDisposable interface is to implement both the Dispose() method and the finalizer(destructor). The code that is common to both these are factored out into a common method that is protected and virtual. The common method takes a parameter to indicate whether it is getting called from a Dispose() method or a finalizer.

Vulnerability and risk

When the code is duplicated, it is possible that a bug that gets fixed in one part is not fixed in the other.

Mitigation and prevention

Implementing the standard design makes it easier to understand the program and avoids potential bugs. When Dispose is implemented, there will invariably be code to free resources. This code will also be part of the finalizer. Therefore it makes sense to factor the common code out.

Vulnerable code example

Copy
  // VIOLATION: This class does not implement the
  // Dispose(bool) method that is called from both
  // Dispose() and the destructor. The code for
  // freeing resources is repeated in both Dispose()
  // and the destructor.
  using System;
  
  public class A : IDisposable
  {
     public A()
     {
         // resource allocated here
     }
     ~A()
     {
         // Free resources here
     }
     public virtual void Dispose()
     {
         // Free resources here.
         GC.SuppressFinalize();
     }
 }

Fixed code example

Copy
  // FIXED: The problem here is fixed by implementing the
  // Dispose method that takes a bool paramter. Note that the
  // method is called from both Dispose() and ~A.
  using System;
  public class A : IDisposable
  {
      private bool _alreadyDisposed = false;
      public A()
      {
         // resource allocated here
     }
     ~A()
     {
         // Dispose() called from the destructor
         Dispose(false);
     }
     public virtual void Dispose()