Introduction
There are a lot of classes (in the .NET framework or perhaps your own classes) that implement the
interface IDisposable
in order to release allocated unmanaged resources. When a user instantiates such
a class then he must call the method 'Dispose' when he is done with that instance of the class. Following
this pattern can easily result in a lot of code, because this pattern should be used with a try-finally block
(or a using statement). This article describes the AutoDisposer
utility class that can reduce a lot of
this code, making your code more readable.
Background
Consider the following code (samplecode1):
private void ClaimResourcesOld()
{
ManualResetEvent resetEvent = new ManualResetEvent(true);
try
{
Brush drawingBrush = new SolidBrush(Color.FromArgb(50, Color.Purple));
try
{
.....
}
finally
{
drawingBrush.Dispose();
}
}
finally
{
((IDisposable)resetEvent).Dispose();
}
}
Using two disposable objects leads to a nesting of try-finally blocks. Note that one could also write the same code
with nested using statements, which reduces the amount of code already somewhat but the nested structure is still required.
Isn't there a way that one could write code with the same functionality without the nesting and with less code? Yes there is;
with a small utility class called AutoDisposer
.
The AutoDisposer class
The AutoDisposer
class is a small utility class that keeps track of a list of disposable objects. The class itself implements
IDisposable
and in the 'Dispose' of the class the tracked elements are disposed. The interface of the class is:
public sealed class AutoDisposer : IDisposable
{
public AutoDisposer() : this(false) { }
public AutoDisposer(bool disposeReverse) { m_DisposeReverse =
disposeReverse; }
public void Add(object obj) { ... }
}
The user must create an instance of the AutoDisposer
class and add disposable objects through the 'Add' method. When disposing the instance
of the AutoDisposer
class all the tracked disposable objects are disposed in the order that they are added. This order can also specified by the
user when the overloaded second constructor of the AutoDisposer
class is used.
When searching on the internet I found the article
Writing Better Software: Managing Unmanaged Resources
which also talks about an AutoDisposer
class, which has a stack-based implementation for tracking disposable objects. The AutoDisposer
class of this article differs on the following issues
- All types of objects can be added, not only objects of type
IDisposable
- The disposable objects are tracked with a list, where the used can specify the order in which to dispose the tracked objects
- The class also deals with disposable null objects, the user doesn't have to check the validness of the disposable object when adding it
This results in an easier to use utility class.
Using the code
When using the AutoDisposer
class samplecode1 can be changed to the following code (samplecode2):
private void ClaimResourcesNew()
{
using (AutoDisposer autoDisposer = new AutoDisposer())
{
ManualResetEvent resetEvent = new ManualResetEvent(true);
autoDisposer.Add(resetEvent);
Brush drawingBrush = new SolidBrush(Color.FromArgb(50, Color.Purple));
autoDisposer.Add(drawingBrush);
.....
}
}
As you can see, this reduces the code drastically and makes the code more readable.
Summary
Reading this article should have made you aware how a small utility class as the AutoDisposer
can make your life easier.
Any comments or questions post below or e-mail them.
History
Version 1.0 - This is the first version of this article.