C#: Design Guide: Disposable Pattern

Design Guide: Disposable Pattern
Both an explicit and an implicit way to free those resources should be provided. Implicit control should always be provided by implementing the protected method Finalize() on an Object (using the destructor syntax in C#). If implemented, the explicit control is provided by a Dispose() method from the IDisposable interface.
 
public class Window : IDisposable
{
   private IntPtr handle; // pointer to a external resource
   private Component Components; // other resource you use
   private bool disposed = false;
   public Window()
   {
      handle = //allocate on the unmanaged side
         otherRes = new OtherResource(…);
   }
   // Implements IDisposable
   public void Dispose()
   {
      Dispose(true);
      GC.SuppressFinalize(this);
   }
   protected virtual void Dispose(bool disposing)
   {
      if (!this.disposed)
      {
         //if this is a dispose call dispose on all state you
         //hold, and take yourself off the Finalization queue.
         if (disposing)
         {
            Components.Dispose();
         }
         ///free your own state (unmanaged objects)
         this.disposed = true;
         Component = null;
         Release(handle);
         handle = IntPtr.Zero;
      }
   }
   //Simply call Dispose(false)
   ~Window()
   {
      Dispose (false);
   }
   //Whenever you do something with this class, check to see if the  
   //state is disposed, if so, throw this exception.
   public void GetWindowHandle()
   {
      if (this.disposed)
      {
         throw ObjectDisposedException(…);
      }
      //…
   }
   //Derived class
   public class MyWindow: Window 
   {
      private bool disposed = false;
      public MyWindow()
      {
      }
      protected override void Dispose(bool disposing)
      {
         if (!this.disposed)
         {
            if (disposing)
            {
               //free any disposable resources you own
            }
            //free your own state
            this.disposed = true;
            base.Dispose(disposing);
         }
      }
   }
}
 
– Do make the Finalize() method protected; Do not make it more visible like public.
– Do call base.Finalize method in your finalizer. Note: this is done automatically with the C# and the MC++ destructor syntax.
– Do suppress finalization of your instance once Dispose has been called, unless there is other work to do in Finalize (not covered by Dispose).
– Do call base.Dispose method if it implements IDisposable.
– Consider not being recreatable. Recreating an object that has already been disposed is often a difficult undertaking.
– Do allow your Dispose method to be called more than once w/o throwing an exception. Do nothing after the first call.
– Other instance methods should check whether resources have been disposed. If so, reacquire the resources or throw an ObjectDisposedException.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s