I have covered the IDisposable interface in my previous posts IDisposable and using in C# and Implementing IDisposable. To make the implementation of IDisposable easier, I have written an abstract base class that handles the details of the IDisposable pattern. The objectives of the class is to:
- Provide a simple, reusable implementation of the disposable pattern.
- Pass all code analysis rules.
The Disposable Class
/// <summary> /// A general implementation of the disposable pattern. /// See http://coding.abel.nu/2012/01/disposable /// </summary> public abstract class Disposable : IDisposable { /// <summary> /// Implementation of IDisposable.Dispose method. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Is this instance disposed? /// </summary> protected bool Disposed { get; private set; } /// <summary> /// Dispose worker method. See http://coding.abel.nu/2012/01/disposable /// </summary> /// <param name="disposing">Are we disposing? /// Otherwise we're finalizing.</param> protected virtual void Dispose(bool disposing) { Disposed = true; } /// <summary> /// Finalizer. /// </summary> ~Disposable() { Dispose(false); } } |
Rewriting the LogWriter
In the Implementing IDisposable post I used a LogWriter
class as a sample. With the Disposable
base class it can be rewritten.
public class LogWriterFromDisposable : Disposable { private StreamWriter m_Stream; public LogWriterFromDisposable(string logFile) { m_Stream = new StreamWriter(logFile, true); m_Stream.WriteLine("Starting logging at {0}", DateTime.Now); } public void WriteLine(string message) { m_Stream.WriteLine(message); } protected override void Dispose(bool disposing) { if (!Disposed && disposing) { m_Stream.Dispose(); } base.Dispose(disposing); } } |
Instead of having an entire section for IDisposable there is now just one method.
Limitations of a Base Class
As C# only supports single inheritance it is only possible to use the Disposable
base class if there is no need to inherit another class, but that is not as hard a limitation at all. Any subclass should always be possible to use anywhere a base class is expected. If the subclass introduced a requirement of disposing, that principle would not hold. It is always preferable to have the base class in a class hierarchy implement IDisposable
if any class requires it. Or put the other way: Never implement IDisposable
in a sub class if the base class doesn’t.