Synopsis: | Implement IDisposable if a class uses unmanaged 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, you must implement the 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
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); } } } |