IDisposable series
- IDisposable and using in C#
- Implementing IDisposable
- Disposable Base Class
- Using and Disposing of WCF Clients
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.
You may also add the support for multi dispose calls by adding a disposed variable checked in Dispose() call.
This is cleaner code, no?
Yes, it’s somewhat cleaner. But it also requires the sub class to implement the
Dispose(bool)
method. And there are cases where that’s not needed. Consider if you have a class that implements an interface that inherits fromIDisposable
. But your specific class does not have any resources that need to be disposed. Then you could just derive form theDisposable
base class to meet theIDisposable
requirement in a way that allows anyone subclassing your class to handle unmanaged resources.