Thomas Alva Edison's light bulb VBInfoZine Home
   An ordinary VB developer shares his own successes and failures
   FREE to registered subscribers.  

The IDisposable design pattern considered harmful

Discusses the pros and cons of the standard IDisposable design pattern used throughout the .NET framework base class library. Provides a blueprint for a better (IMHO) IDisposable design pattern.
When writing the outline for this article, the very first item on my list was to "rehash shortly what's IDisposable for". But as I tried to start to actually write the "rehash" I quickly realized that it would be nonsense--the .NET framework documentation does a good job doing it (and I definitely won't "catch" anyone's attention publishing snippets from the docs:-). If you are not already familiar with the IDisposable interface and the associated design pattern, I encourage you to first read through the MSDN documentation.

Here is the MSDN code from the article (click to expand / collapse the code):

So what's wrong with the code?

There are two things why I don't like it.

The first one is the necessity to declare and maintain the disposed flag in each and every derived class.

The other reason why I don't like the code is very subjective and it is the naming of the Protected Dispose(Boolean) method and it's disposing parameter. After all, we are inside Dispose method, so the disposing flag should always be True, right? Wrong! When called by a user code (presumably inside in a Finally block), the flag is True. When called from the Finalize method, the flag is False. Not quite intuitive, IMHO.

So what can be done to improve the design patter for my likings?

The first thing I would suggest is to expose the private disposed flag through a protected property:

Private disposed As Boolean
...
Protected ReadOnly Property IsDisposed() As Boolean
Get
	Return disposed
End Get
In addition, I would also implement a CheckDisposed method for checking the disposed flag and raising the ObjectDisposedException exception, because the check should be included in the prolog of (at least) every Public method of a class:
Protected Sub CheckDisposed()
	If disposed Then
		Throw New ObjectDisposedException()
	End If
End Sub
By implementing this method, you save two lines of code for each method where it is used.

Finally, in order to avoid to remember when disposing is True or False and what kind of resources to release, I would implement the following two methods in a base class:

Protected Overridable Sub DisposeManagedResources()
	...
End Sub

Protected Overridable Sub DisposeUnmanagedResources()
...
End Sub
The base class' IDisposable implementation would now look like this:
Public Sub Dispose() Implements IDisposable.Dispose
	If disposed Then
		Return
	End If

	Me.DisposeManagedResources()
	Me.DisposeUnmanagedResources()
	
	disposed = True

	GC.SuppressFinalize(Me)
End Sub

Protected NotOverridable Sub Finalize()
	If Not disposed Then
		Me.DisposeUnmanagedResources()
	End If
End Sub
By making the Finalize method not overridable, I'm ensuring that no inheritor will be able to violate the rules dictated by the design pattern.

To wrap things up, let's summarize, what an inherited class implementer has to remember using both approaches.

The "classic" approach:

  • Override the protected Dispose(Boolean) method and call MyBase.Dispose(disposing).
  • Declare a private disposed flag and set it to True at the end of the Dispose(Boolean) method.
  • Check the disposed flag where appropriate using the "three-liner" If disposed Then statement.

My improved approach:

  • Override the DisposeManaged/UnmanagedResources as necessary and call the MyBase implementation in each overridden method.
  • Check the disposed flag where appropriate using the "one-liner" CheckDisposed statement.

So what approach will you use? If you don't like my verbose methods and stick with the classic approach, I encourage you to use the CheckDisposed method at least. (I guess it's so obvious that most people already use some variation of the CheckDisposed method).

PS: Have you ever looked at the list of classes that implement IDisposable? There are 85 of them in the .NET framework BCL version 1.1. And for some of them I was very surprised to see they implement IDisposable! Have you written some GDI+ code and used the Matrix class? OK. Have you disposed all the matrix instances you've used? Not? It is likely then, your app is more resource intensive than it could be.

© Palo Mraz - June 14, 2003

 ©2003-2007 Palo Mraz. All Rights Reserved.   See my 'new browser window' policy