IDisposable Interface and Managed Resources

Very scarcely I'll see a developer disposing an object and I'll admit that I'm one of those developers who doesn't do this enough.  We're all aware of the garbage collector that runs at indeterminate times to clean up the mess we've left behind, so who cares whether we actually call an object's Dispose() method?  Why not just wait until the garbage collector does its thing?

Because the garbage collector won't free up unmanaged resources in your code.  These are files, handles, and streams.  These objects implement the IDisposable interface, which has only one method, Dispose().

In C#, there are two techniques for disposing of an object that implements the IDisposable interface:

  • In a try / finallyblock:
    var memoryStream = new MemoryStream();
    var bytes = new byte[128];
    try
    {
    	memoryStream.Read(bytes, 0, bytes.Length);
    }
    finally
    {
    	memoryStream.Dispose();
    } 
  • In a using statement:
    var memoryStream = new MemoryStream();
    var bytes = new byte[128];
    using (memoryStream)
    {
    	memoryStream.Read(bytes, 0, bytes.Length);
    } 

In the case of a using statement, the Dispose() method is implied at the end and is guaranteed to run even if an exception is hit; it's a fancy way of implementing the try / finally block.

In addition, if any of your classes use unmanaged resources, you'll want to implement IDisposable too.  Here's an example.  Please feel free to let me know if you see any issues with this implementation.

public class SpecializedMemoryStream : IDisposable
{
	private MemoryStream _memoryStream;
	private bool _isDisposed;

	/// <summary>
	/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
	/// </summary>
	public void Dispose()
	{
		Dispose(true);

		// Tell the garbage collector that the finalize destructor doesn't need to be called for this object
		GC.SuppressFinalize(this);
	}

	/// <summary>
	/// The finalize destructor
	/// </summary>
	~SpecializedMemoryStream()
	{
		Dispose(false);
	}

	protected virtual void Dispose(bool isDisposingManagedResources)
	{
		// Check if this method was previously called:
		if (_isDisposed)
		{
			return;
		}

		if (isDisposingManagedResources)
		{
			// Free up managed resource:
			if (_memoryStream != null)
			{
				_memoryStream.Dispose();
				_memoryStream = null;
			}
		}

		// Dispose any native resources here.

		_isDisposed = true;
	}
}

It's definitely good practice to be on the eye out for objects that implement the IDisposable interface; although it takes a bit more code to implement correctly, it frees up resources that otherwise wouldn't have been reclaimed until your application closes and might help to prevent memory leaks along the way.

References:
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
http://msdn.microsoft.com/en-US/library/ms244737(v=VS.80).aspx 

Leave a Reply

Your email address will not be published. Required fields are marked *