Use IDisposable to Release .NET Resources
The Dispose pattern properly releases resources but imposes overhead.
by Mickey Williams
VSLive! Orlando, September 18, 2002
Note: Mickey Williams is presenting "Apply IHttpHandler and IHttpModule" at ASP Live! Orlando, Wednesday, September 18.
You use the Dispose pattern to properly release non-memory resources such as database connections, Win32 interop components, and operating system handles. You can't rely on garbage collection to free these resources quickly, because garbage collection is triggered by memory pressure in the managed heap. You can quickly consume scarce resources such as database connections, adversely affecting the scalability of your application. However, you should not implement the Dispose pattern when it isn't required, because it imposes overhead that you can avoid in most cases.
The Dispose pattern is formalized in .NET through the IDisposable interface, which includes a single method, Dispose:
interface IDisposable
{
void Dispose();
}
The most clear-cut case where a class should implement IDisposable is when instances of the class will have strong ownership over an unmanaged resource, such as a native database connection or operating system handle.
In addition, note a frequently overlooked case where you should implement IDisposable. When a class implements IDisposable, proper use of its instances requires the Dispose method to be called when the object is no longer needed. When you implement a class that owns other classes that implement IDisposable, therefore, you must ensure that Dispose is invoked. This usually means that you must implement IDisposable in that class, even though it might not deal with unmanaged resources directly.
Here's the typical pattern for implementing IDisposable properly:
public class SlalomRacer: IDisposable
{
bool _disposed = false;
public bool IsDisposed
{
get { return _disposed; }
set { _disposed = value; }
}
~SlalomRacer()
{
InternalDispose(false);
}
public void Dispose()
{
InternalDispose(true);
}
protected void InternalDispose(bool disposing)
{
if(disposing)
{
GC.SuppressFinalize(this);
_managedThing.Dispose();
}
_unmanagedThing.Dispose();
}
[...]
}
Back to top
|