TICS Coding Standard Viewer 
TIOBE Software Quality Framework
Print-friendly version
©TIOBE Software www.tiobe.com
 
C# Coding Standard
Search

Rule:  5@113Checked automatically with code checker

Synopsis:Implement IDisposable if a class uses unmanaged/expensive resources, owns disposable objects or subscribes to other objects
Language:C#
Severity Level:2
Category:Object lifecycle


Description:

If a class uses unmanaged resources such as objects returned by C/C++ DLLs, or expensive resources that must be disposed of as soon as possible, you must implement the IDisposable interface to allow class users to explicitly release such resources.

A class should implement the IDisposable interface, in case it creates instances of objects that implement the IDisposable interfaces and a reference to that instances is kept (note that if the class transfers ownership of the create instance to another object, then it doesn't need to implement IDisposable).

The following code snippet shows the pattern to use for such scenarios.

Beware also the protection against multiple dispose attempts via the 'already disposed status' member.

public class ResourceHolder : IDisposable
{
	protected bool mIsObjectInstanceAlreadyDisposed = false;

	///<summary>
 	///Implementation of the IDisposable interface
	///</summary>
	public void Dispose()
	{
		// Call internal Dispose(bool)
		Dispose(true);

		// Prevent the finalizer from being called
		GC.SuppressFinalize(this);
	}
	///<summary>
	/// Central method for cleaning up resources
	///</summary>
	protected virtual void Dispose(bool disposing)
	{
		if ( ! mIsObjectInstanceAlreadyDisposed)
		{
			// If disposing is true, then this method was called through the 
			// public Dispose() 
			if (disposing)
			{
				// Release or cleanup managed resources
			}

			// mDatabaseConnection could be null if an exception has occurred
                        if (mDatabaseConnection != null) { 
                               // Always release or cleanup (any) unmanaged resources, E.G.:
			       if (mDatabaseConnection.State == System.Data.ConnectionState.Open)
			       {
				       mDatabaseConnection.Close();
                                       mDatabaseConnection = null;
			       }
                        }

			mIsObjectInstanceAlreadyDisposed = true;
		}
	}
	~ResourceHolder()
	{
		// Since other managed objects are disposed automatically, we 
		// should not try to dispose any managed resources (see Rule 5@114).
		// We therefore pass false to Dispose()
		Dispose(false);
	}
}

If another class derives from this class, then this class should only override the Dispose(bool) method of the base class. It should not implement IDisposable itself, nor provide a finalizer (unless this class also contains 'unmanaged resources').
The derived class only needs to make sure to clean up it's own managed resources and calling the base class' finalizer.

public class DerivedResourceHolder : ResourceHolder
{
	protected override void Dispose(bool disposing)
	{
		if ( ! mIsObjectInstanceAlreadyDisposed)
		{
			if (disposing)
			{
				// Release or cleanup managed resources of this derived 
				// class only.
			}
			// Always release or cleanup (any) unmanaged resources ...
			// ... by calling Dispose on our base class.
			base.Dispose(disposing);
		}
	}
}