Pages

Friday, September 04, 2009

Correct usage of the .NET dispose pattern.

This wiki is to help with the correct usage of the dispose pattern.

Useful excerpt below; from http://blogs.msdn.com/bclteam/archive/2007/10/30/dispose-pattern-and-object-lifetime-brian-grunkemeyer.aspx“A disposable type needs to implement IDisposable & provide a public Dispose(void) method that ends the object’s lifetime. If the type is not sealed, it should provide a protected Dispose(bool disposing) method where the actual cleanup logic lives. Dispose(void) then calls Dispose(true) followed by GC.SuppressFinalize(this). If your object needs a finalizer, then the finalizer calls Dispose(false). The cleanup logic in Dispose(bool) needs to be written to run correctly when called explicitly from Dispose(void), as well as from a finalizer thread. Dispose(void) and Dispose(bool) should be safely runnable multiple times, with no ill effects.“

Example:
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyClass : IDisposable
{
private ManagedResource managedResource = new ManagedResource();
private bool disposed = false;

public void Dispose()
{
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// Dispose managed resources.
this.managedResource.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.


this.disposed = true;
}
}

// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources itself, but leave the other methods
// exactly as they are.
~MyClass()
{
// Finalizer calls Dispose(false)
Dispose(false);
}

}

Over-riding the dispose method in a derived class:

private System.ComponentModel.IContainer components = null;

///
/// Clean up any resources being used.
///

/// true if managed resources should be disposed;
otherwise, false.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}

Is it mandatory to have GC.SuppressFinalize(this) in the Dispose(void) block?

It is not mandatory to have GC.SuppressFinalize(this); unless you have a finalizer method. However it is recommended to have GC.SuppressFinalize(this); for the cases even without finalizer simply for the consistency sake. Having a “GC.SuppressFinalize(this);” in the latter case would be just like calling an empty method.

References:
http://msdn.microsoft.com/en-us/library/ms244737(VS.80).aspx
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae