Disposable Base Class

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.

This post is part of the IDisposable series.<< Implementing IDisposableUsing and Disposing of WCF Clients >>

  • Samuel on 2015-12-09

    You may also add the support for multi dispose calls by adding a disposed variable checked in Dispose() call.

  • Adam Hancock on 2017-02-17

    This is cleaner code, no?

    public abstract class Disposable : IDisposable
    {
      protected bool Disposed { get; private set; }
     
      /// 
      /// Frees resources
      /// 
      public void Dispose()
      {
        if (!Disposed)
        {
          Disposed = true;
          Dispose(Disposed);
        }
        GC.SuppressFinalize(this);
      }
     
      protected abstract void Dispose(bool disposing);
    }

    • Anders Abel on 2017-02-21

      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 from IDisposable. But your specific class does not have any resources that need to be disposed. Then you could just derive form the Disposable base class to meet the IDisposable requirement in a way that allows anyone subclassing your class to handle unmanaged resources.

  • Leave a Reply

    Your name as it will be displayed on the posted comment.
    Your e-mail address will not be published. It is only used if I want to get in touch during comment moderation.
    Your name will be a link to this address.
Software Development is a Job – Coding is a Passion

I'm Anders Abel, a systems architect and developer working for Kentor in Stockholm, Sweden.

profile for Anders Abel at Stack Overflow, Q&A for professional and enthusiast programmers

Code for most posts is available on my GitHub account.

Popular Posts

Archives

Series

Powered by WordPress with the Passion for Coding theme.