Disposable Pattern in .NET

Garbage collector (GC) is a blessing in .NET, if you happen to program in C++ in the past, where it was one of the prime responsibility of a developer was to manage the heap. That means when ever an object is created on the heap, it has to be deleted in the corresponding method or in the destructor, if the life is object long. And if he/she forgot to do so, then the nightmare begins in the form of memory leaks and troubleshooting may take hours and some times even days. But that's the story of the past, we as a C# developers are blessed, because we have a world class Garbage Collector comes right out of the box with .NET framework and an integral part of the CLR. What does it mean?? That means we need not to worry about deleting/disposing the objects being created on the heap, and GC, at runtime manage the heap, and its robust algorithm sees when some object is no longer needed, it silently dispose it off. Very clever, but you know what, not that clever. It doesn't know how to close the resources like a Database connections,  file handle when it is no more needed, doesn't know what to do when the Network connection needs to be released or closed etc. etc. First thing that would come into your mind, why don't we use the finalizer/destructor to take care of this scenario?? Like we close these resource handles in the finalizers, how's that?? You can do so, but it will not work, why?? due to the GC’s non-deterministic behavior, it may take longer than expected that the destructor/finalizer will be called, and there will be a deadlock, that is you might need to reuse some resource, and since the objects destructor is not called, the object is not releasing it, you are stuck, complete deadlock. So what we do now?? Good news is, you can do it elegantly with the help of proper usage of Disposable Pattern, which is nothing more than implementation of Template Design Pattern (GOF). Before going into the details of the pattern, lets first take a look at what are disposable objects and how the .NET framework facilitates us in this regard.

IDisposable Objects

It is recommended that any custom object that has acquired or owns system/native resources should implement IDisposable interface in order to participate in the disposable mechanism. What does that mean?? Does the CLR will  take care of disposing the object automatically. Not really, it is the consumers responsibility to call the Dispose method, as soon as the object is no more needed. .NET framework itself has created many disposable classes as shown in Figure-1. All of these classes if you look at them are responsible for interacting system resources, like memory, file system, network stream, pipes etc. etc. That's why they all are implemented the IDisposable interface, so the consumer of these types should be aware of its usage and release them as soon as they are done.

ClassDiagram2 Figure 1

Here is one i am using as an example, StringWriter:-

Code Snippet
  1. public static class TXmlUtils<T> where T : class
  2. {
  3.     public static string ToString2(T context)
  4.     {
  5.         string xmlString = string.Empty;
  6.         StringWriter stringWriter = new StringWriter();
  7.         try
  8.         {
  9.             XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
  10.             xmlSerializer.Serialize(stringWriter, context);
  11.             xmlString = stringWriter.ToString();
  12.         }
  13.         finally
  14.         {
  15.             IDisposable disposable = stringWriter as IDisposable;
  16.             if (disposable != null)
  17.             {
  18.                 disposable.Dispose();
  19.             }
  20.         }
  22.         return xmlString;
  23.     }

This is a generic method as you can see,converts a generic context object into Xml string. It does this with the help of an IDisposable class StringWriter. When it is done {using} it, disposes it off in the finally block, that actually releases all the resources StringWriter is holding off. It is so common in .NET that it provides a keyword {using} to encapsulate this scenario. Here is a rewrite of the above method: The {using} when expanded by the pre-compiler/compiler, takes the above mentioned form.

Code Snippet
  1. public static string ToString(T context)
  2.         {
  3.             string xmlString = string.Empty;
  4.             using (StringWriter stringWriter = new StringWriter())
  5.             {
  6.                 XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
  7.                 xmlSerializer.Serialize(stringWriter, context);
  8.                 xmlString = stringWriter.ToString();
  9.             }
  10.             return xmlString;
  11.         }

As you may have noticed by now, that the implementation of IDisposible has nothing to do with Garbage Collector’s cleanup mechanism. It is the consumer’s duty to dispose off the object. But the finalizer / destructor do get called by the Garbage Collector for final cleanup, the only problem is, the destruction process is non-deterministic. That's why when you are disposing an object you should take care of finalizer too that is if something needs to be disposed at the very end like un-managed resources, when implementing IDisposable and that's how a Disposable pattern get evolved, that is nothing more than proper implimentation of IDisposable interface especially where class derivatives are involved.

Disposable Pattern and Its Implementation 

Take a look at the following figure (Figure-2), the Disposable pattern is very simple. The consumer/client consumes  an IDisposable based class and calls the Dispose method, when it is done using it, that's it. No more no less. The only thing is how these Dispose methods are being implemented internally, that is the crux of this pattern. Question then arises, Is the Disposable Pattern is a design pattern or its just an implementation/coding pattern. ? You are the better judge But it is for sure, If you look at it closely, it actually uses “Template Design Pattern”, for its implementation.

 disposable pattern Figure-2

As you can see from the Class Model (Figure-2) and the Sequence Diagram (Figure-3A), DisposableBase is IDisposable, and implements the Dispose() method. The Dispose() method further calls two methods, Dispose(true) and GC.SuppressFinalize(this) methods. Dispose(bool) is actually a virtual method, provides extensibility for the derived ones to implement their disposing mechanism. This Dispose(.) method when called with a true parameter, disposes all the resources, managed as well as un-managed/native ones. And when it is called with a false parameter, only disposes the un-managed resources. Dispose() method also calls GC.SuppressFinalize(this), that actually tells the Garbage Collector (GC) not to call Finalizer/Destructor (~DisposableBase). 


Figure-3A  -- Figure-3B

Here is the implementation of the Disposable pattern in C#:

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  6. namespace Shams.DisposablePattern
  7. {
  8.     public abstract class DisposableBase : IDisposable
  9.     {
  10.         public DisposableBase() { }
  12.         /// <summary>
  13.         /// Destructor/Finalizer, releases native resources
  14.         /// </summary>
  15.         ~DisposableBase()
  16.         {
  17.             // Virtual Dispose called..
  18.             Dispose(false);
  20.             System.Diagnostics.Trace.WriteLine("DisposableBase.Finalizer called...");
  21.         }
  23.         #region IDisposable Members
  25.         public void Dispose()
  26.         {
  27.             this.Dispose(true);
  29.             // Tell GC not to call the Finalizer/Destructor...
  30.             GC.SuppressFinalize(this);
  31.         }
  33.         #endregion
  35.         protected virtual void Dispose(bool disposing)
  36.         {
  37.             if (disposing)
  38.             {
  39.                 // Free other state (managed objects).
  41.                 System.Diagnostics.Trace.WriteLine("DisposableBase.Dispose(disposing)/managed called...");
  42.             }
  43.             // Free your own state (unmanaged objects).
  44.             // Set large fields to null.
  45.             try
  46.             {
  47.                 System.Diagnostics.Trace.WriteLine("DisposableBase.Dispose(disposing)/un-managed called...");
  48.             }
  49.             catch (Exception ex)
  50.             {
  51.                 System.Diagnostics.Trace.WriteLine(ex.ToString());
  52.             }
  53.         }
  55.         public abstract void DoSomeWork();
  56.     }
  57. }


Note that even if we have an explicit mechanism in place, that is the Dispose() method, we also provide an implicit mechanism too in the form of Finalizer/Destructor as a backup to prevent from memory leakage of any un-managed/native resources, by calling Dispose(false) to clean them up. So just in case if the consumer fails to call Dispose() method, these resources will eventually be cleaned up by the GC {Please Ref.: (lines 15-20 above) and the the sequence diagram (Figure-3B)}.

Now, take a look at the following derived class, where we are only overriding the Dispose(bool) method (lines 25-43), when it is done disposing its own resources, disposes the base ones by calling base.Dispose(bool).

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  6. namespace Shams.DisposablePattern
  7. {
  8.     public class DisposableDerived : DisposableBase
  9.     {
  10.         public DisposableDerived() { }
  12.         /// <summary>
  13.         /// Destructor/Finalizer, releases native resources
  14.         /// </summary>
  15.         ~DisposableDerived()
  16.         {
  17.             // Commented, No need of it, the base class takes care of it
  18.             //Dispose(false);
  20.             System.Diagnostics.Trace.WriteLine("DisposableDerived.Finalizer called...");
  21.         }
  23.         #region IDisposable Overrides
  25.         protected override void Dispose(bool disposing)
  26.         {
  27.             try
  28.             {
  29.                 if (disposing)
  30.                 {
  31.                     // Clean up managed resources
  33.                     System.Diagnostics.Trace.WriteLine("DisposableDerived.Dispose(disposing)/managed called...");
  34.                 }
  36.                 // Clean up native/un-managed resources
  37.                 System.Diagnostics.Trace.WriteLine("DisposableDerived.Dispose(disposing)/unmanaged called...");
  38.             }
  39.             finally
  40.             {
  41.                 // finally, dispose the base one...
  42.                 base.Dispose(disposing);
  43.             }
  44.         }
  45.         #endregion
  47.         public override void DoSomeWork()
  48.         {
  49.             System.Diagnostics.Trace.WriteLine("Some Work Done...");
  50.         }
  51.     }
  52. }


Lets now take a look at the Consumer. The consumer, creates an IDispoasble based concrete class, DisposableDerived, and when some useful work is done, the in-built {Using} mechanism disposes it off, by calling DisposableDerived.Dispose(). Here is the sequence diagram for it (Figure-6):

sequence1 Figure-6

And here is the corresponding implementation of it in C#. You can see from the output (lines 19- 23, Figure-7) that all the Disposables are called properly.

Code Snippet
  2. using System;
  3. namespace Shams.DisposablePattern
  4. {
  5.     public class Consumer
  6.     {
  7.         public IDisposable disposable;
  9.         public Consumer() { }
  11.         public static void Main(string[] args)
  12.         {
  13.             using (DisposableBase disposable = new DisposableDerived())
  14.             {
  15.                 disposable.DoSomeWork();
  16.             }
  18.             /* Output is:
  19.              *  Some Work Done...
  20.                 DisposableDerived.Dispose(disposing)/managed called...
  21.                 DisposableDerived.Dispose(disposing)/unmanaged called...
  22.                 DisposableBase.Dispose(disposing)/managed called...
  23.                 DisposableBase.Dispose(disposing)/un-managed called...
  24.             */
  26.             /* Output, If you comment out the
  27.              * GC.SuppressFinalize(this); from the DisposableBase.Dispose() method
  29.                 Some Work Done...
  30.                 DisposableDerived.Dispose(disposing)/managed called...
  31.                 DisposableDerived.Dispose(disposing)/unmanaged called...
  32.                 DisposableBase.Dispose(disposing)/managed called...
  33.                 DisposableBase.Dispose(disposing)/un-managed called...
  35.                 The thread 0x3f0 has exited with code 0 (0x0).
  36.                 The thread 0x2134 has exited with code 0 (0x0).
  38.                 DisposableDerived.Finalizer called...
  39.                 DisposableDerived.Dispose(disposing)/unmanaged called...
  40.                 DisposableBase.Dispose(disposing)/un-managed called...
  41.                 DisposableBase.Finalizer called...
  42.              */
  43.         }
  44.     }//end Consumer
  45. }


When you run the app, you’ll see the output as shown above (lines 19-23). Just in case you, comment out the GC.SuppressFinalize(.) method from the base class, you’ll notice that the Finalizer is called, that actually disposes of the un-manged or native resources (see lines 26-41 above). With all said here is a reference for further exploration: Implementing Finalize and Dispose to Clean Up Unmanaged Resources [MSDN]

That's all for now folks, I hope it was helpful. I appreciate you please leave your valuable feedback. Enjoy :)

If you enjoyed reading this blog, leave your valuable feedback and consider subscribing to the RSS feed. You can also subscribe to it by email. Also, you can follow me on Twitter. Thank you!

Comments are closed