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 (12) -

Cerebral Boost Review
3/19/2018 7:59:19 PM #

Hi there are using Wordpress for your site platform? I'm new to the blog world but I'm trying to get started and create my own. Do you need any html coding expertise to make your own blog? Any help would be greatly appreciated!

Claira Care
3/19/2018 10:07:00 PM #

This web site certainly has all of the information I wanted about this subject and didn?t know who to ask.

Claira Care Cream Reviews
3/19/2018 10:07:43 PM #

Merely wanna say that this is very beneficial, Thanks for taking your time to write this.

Claira Care Cream Reviews
3/19/2018 10:07:53 PM #

Enjoyed studying this, very good stuff, thanks.

ThermoBurn Weight loss
3/19/2018 11:01:44 PM #

What i don't realize is actually how you are not really much more well-liked than you may be right now. You're so intelligent. You recognize thus significantly in relation to this subject, made me in my view consider it from numerous varied angles. Its like men and women aren't interested except it's one thing to do with Lady gaga! Your individual stuffs great. Always take care of it up!

ThermoBurn Fat Burner
3/19/2018 11:02:18 PM #

Hello there, just became alert to your blog through Google, and found that it's truly informative. I am gonna watch out for brussels. I will appreciate if you continue this in future. Numerous people will be benefited from your writing. Cheers!

Enduraflex Performance Booster
3/19/2018 11:09:44 PM #

Unquestionably consider that which you stated. Your favorite justification appeared to be on the web the easiest thing to take note of. I say to you, I definitely get irked while other people think about concerns that they just do not recognise about. You managed to hit the nail upon the highest and outlined out the entire thing with no need side-effects , people can take a signal. Will probably be back to get more. Thank you

Enduraflex Performance Plus
3/19/2018 11:09:46 PM #

I do accept as true with all the ideas you have offered for your post. They're very convincing and will certainly work. Nonetheless, the posts are very short for starters. Could you please lengthen them a bit from next time? Thanks for the post.

Enduraflex Performance Booster
3/19/2018 11:09:49 PM #

I do believe all of the ideas you have offered for your post. They're really convincing and will definitely work. Still, the posts are too quick for newbies. May you please lengthen them a bit from subsequent time? Thank you for the post.

Enduraflex Testo Boost
3/20/2018 12:14:29 AM #

Hey there, You've done an incredible job. I will definitely digg it and personally suggest to my friends. I'm confident they'll be benefited from this site.

Slim Biotic Forskolin
3/20/2018 2:07:04 AM #

Thank you, I have just been looking for info about this subject for a long time and yours is the greatest I've discovered till now. But, what about the bottom line? Are you certain about the source?

3/20/2018 2:54:29 AM #

A lot of thanks for all of your hard work on this blog. My niece loves participating in research and it's really easy to understand why. Most of us know all concerning the powerful mode you provide powerful solutions through the website and even improve response from visitors on the idea so our daughter is in fact being taught a great deal. Enjoy the rest of the year. You're performing a wonderful job.[X-N-E-W-L-I-N-S-P-I-N-X]I'm extremely impressed with your writing talents as smartly as with the structure for your blog. Is this a paid theme or did you modify it your self? Either way stay up the excellent quality writing, it is uncommon to peer a nice blog like this one nowadays.

Thin Garcinia Cambogia
3/20/2018 3:00:14 AM #

You have remarked very interesting details! ps decent site.

Pure Essence CBD Reviews
3/20/2018 3:34:35 AM #

Appreciate it for helping out, fantastic information.

Pure Essence CBD Oil Reviews
3/20/2018 3:35:45 AM #

Aw, this was an incredibly nice post. Spending some time and actual effort to create a very good article? but what can I say? I put things off a lot and never seem to get nearly anything done.

Pure Essence CBD Oil Reviews
3/20/2018 3:36:28 AM #

magnificent put up, very informative. I'm wondering why the opposite experts of this sector don't notice this. You should continue your writing. I'm confident, you've a huge readers' base already!

Pure Essence CBD Oil Reviews
3/20/2018 3:38:04 AM #

I  the efforts you have put in this, regards for all the great content.

Pure Essence CBD
3/20/2018 3:43:56 AM #

Your way of explaining everything in this paragraph is actually nice, all can without difficulty be aware of it, Thanks a lot.

Add comment