Implementing the IDisposable interface
First it seems that the IDisposable interface is really easy to implement. It has only one method and how hard could it be to implement one method?! Soon after the first random exceptions happen you might realize that the IDisposable interface is a tough one.
There are a few things that should be considered when implementing the destruction process of a .NET class:
- Make sure you have a destructor in the class: to ensure that unmanaged resources get cleaned up.
- Try to follow a pattern that you can easily apply to all the various classes that need disposal.
- Try to follow the guidelines for the .NET IDisposable interface.
Looking at the samples you will see that Microsoft usually implements a method that can be called form both, the destructor and the IDisposable’s Dispose method. I usually follow that and create a second (and private; could also be protected) Dispose method that takes an argument saying it was called from the destructor or the IDisposable’s Dispose.
In that overloaded Dispose method I make sure that during a call from the destructor no managed class gets touched at all. That’s important because during garbage collection managed class instances get destroyed in a random order. It’s not guaranteed that any of the managed instances that you hold inside your class (as class fields) is still alive during a destructor call. This is one of the most important things to keep in mind when implementing the IDisposable interface.
I pointed out “managed classes” because pointers to native code are still alive (the GC ignores them). You need to manually clean them up inside of the overloaded Dispose method.
My code snippet for an implementation looks like this:
{
// this field is true when the class has been disposed.
private bool _disposed;
/// <summary>
/// Destructor of the Foo Class.
/// </summary>
~Foo()
{
// call the dispose method with false since
// the garbage collector is destroying the
// instance.
Dispose(false);
}
/// <summary>
/// Disposes the current instance of the class.
/// </summary>
/// <param name="disposing">True when this method is
/// called form the dispose method of IDisposable.</param>
private void Dispose(bool disposing)
{
// return if this instance is already disposed.
if (_disposed)
return;
if (disposing)
{
// it is save to access member variables (class fields)
// inside of this block. This block is only entered
// when the Dispose method of IDisposable is invoked.
// you should dispose (call the Dispose method) of
// member variables (class fields) inside of this block.
}
// outside of the "disposing" block it is only save to
// release native (unmanaged) resources. If you have
// class fields holding a pointer to a native piece
// of memory you can safely free that.
// it is not save to access other managed classes from
// here. They might have been destroyed by the garbage
// collector already! There is no way to force the GC
// to destroy objects in a certain order.
_disposed = true;
}
#region IDisposable Members
/// <summary>
/// Disposes the current instance of the class.
/// </summary>
public void Dispose()
{
// call the dispose method with true, since
// we are inside the Dispose method of IDisposable.
Dispose(true);
// make sure the GC is not going to call the destructor
// of this class again. This saves time during garbage
// collection.
GC.SuppressFinalize(this);
}
#endregion
}






Published on Aug 24th, 2008 —
Tags:
Chris, in a managed environment like .net could you give some examples of stuff you’d have to manually clean up (excluding streams and interop activities with unmanaged classes) ? i get a bit confused when it comes to defining what has a large footprint (memory) and in turn must be handled manually (through destrutors and impementing IDispose. Thank you.
Comment by Donald — September 2, 2008 @ 5:30 am
What needs to be handled manually is only native objects. Like if you use interop then you create system resources that are unmanaged and they need to be cleaned up (streams fall into that category because underneath they implement the native system streams).
Other than that the GC takes care of cleaning up stuff. Even if you wanted to you can’t manually free managed objects. They are always and only removed by the GC.
Comment by Christian Liensberger — September 3, 2008 @ 11:12 pm
Thanks for the clarification. :). After running some tests yesterday on Encrypto i realised i did not implement IDisposable for my heavy classes, in turn it made the app take more memory. your resource will come in handy when i start optimising the tool. Thanks
Comment by donald — September 5, 2008 @ 4:59 am
There is another case when you want to implement the IDisposable interface: Do it whenever you have a class that has a disposable field. In this case the Dispose method should just forward the call in order to make sure that everything is disposed of as early as possible.
Also equally important: Don’t just implement a Finalizer “just to have one”. Only implement one if you’re holding a reference to an unmanaged resource. Since .NET 2.0 provides SafeHandles this case should be VERY rare.
See for more information about this topic. Actually there are many rules for implementing Finalizers/IDisposable listed on the page, it’s not just about unmanaged resources as the title implies.
For more information on many topics like this I highly recommend reading the book “Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries” by Krzysztof Cwalina and Brad Abrams. It’s really a great resource.
Comment by Thomas Dallmair — September 5, 2008 @ 7:44 pm
Thank you for adding these resources to the discussion.
Comment by Christian Liensberger — September 7, 2008 @ 3:49 pm
thanks guys, about the tool that i was talking about. for some reason it has a peak of 70-80 mb on my pc ( which led me to believe i was leaking memory some where) but when i deployed and studied it on other pc’s its peak was only 12 mb ! Any ideas as to what is going on ?
Comment by gogole — September 11, 2008 @ 5:10 am
This could be multiple things:
1) do you have a debugger attached when you measure the memory usage?
2) do you have more memory than on the other machine?
3) how does memory usage generally look compared both machines?
4) …
Usually .NET allocates a little bit more memory that is required to use it later on. It also frees memory not immediately but when it hasn’t been used for a while. This is done because memory allocation from the system is quite slow. By allocating a little bit more and releasing a little bit later some of these requests from the system can be avoided and that speeds up creation of objects etc.
Comment by Christian Liensberger — September 12, 2008 @ 10:52 pm
1) nope, i do not have a dubugger attached.
2)nope, the two pc’s all use 1gb of ram.
3)the other machine uses about 30% of ram being used by the same tool om my pc.
I’m implementing IDisposable for the heavyweight classes, that should help release memroy faster.
Comment by Gogole — September 15, 2008 @ 6:28 am
It doesn’t release memory faster when you implement the interface. It only allows you to free up unmanaged memory or call Dispose on class instances that you hold inside of your class that will then eventually free up their unmanaged resources.
Comment by Christian Liensberger — September 16, 2008 @ 11:28 pm