IDisposable Part 3 – Encapsulating an IDisposable class

For part 3 of my series on IDisposable, I’m going to focus on ownership of other IDisposable resources.  In this series, we’re going to build on our LicenseAGenerator class from Part 2, encapsulating inside of a class which will use it repeatedly.

In this case, we’re going to suppose that we have a class that repeatedly needs to check licenses.  If we were doing this infrequently, we could just create a new LicenseAGenerator as needed, and use it.  However, if we were going to be doing this frequently, we might want to construct our license generator one time, and preserve it for the lifetime of our new object.  In this case, we might not want to continually construct and dispose our generator, especially if the generator construction is time consuming.

So, say we have a class “A”, and a factory which constructs these classes for us, checking the license.  Our A class does not have a public constructor, and must be created via our factory.  Our factory class is going to “own” a LicenseAGenerator, which is a disposable resource.  If your class encapsulates a disposable resource, and has a sense of ownership of it, it is a good idea to implement IDisposable on the class as well.  This allows the user of your class to dispose of the native resources deterministically.

In this case, our factory class could look something like this:

/// <summary>
/// Our main factory class
/// </summary>
/// <remarks>Note that this is marked sealed.</remarks>
public sealed class AFactory : IDisposable
{
    /// <summary>
    /// Our license generator.  This is constructed with our class
    /// </summary>
    private LicenseAGenerator generator = new LicenseAGenerator();

    /// <summary>
    /// We still need a way to verify that our object has not been disposed.
    /// </summary>
    private bool disposed;

    /// <summary>
    /// Creates an A class for a specific user.
    /// </summary>
    /// <param name="user">The user.</param>
    /// <returns>A newly constructed instance of A.</returns>
    public A CreateForUser(string user)
    {
        // We still need to make sure we haven't been disposed in this case
        if (this.disposed)
            throw new ObjectDisposedException("AFactory");

        // Here, we use our IDisposable resource to check our license
        if (this.generator.LicenseValid(user))
        {
            return new A();
        }
        throw new LicenseException(String.Format("User {0} does not have a valid license."));
    }

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        // In this case, we do not need to provide a virtual method, since we're in a sealed class!
        // We still need to mark us as disposed, and dispose of our managed resources
        this.disposed = true;
        this.generator.Dispose();
    }
}

There are a few things different about this from our previous IDisposable implementations.

  1. We decided to seal this class.  That simplifies our usage, because we no longer have to provide a way for subclasses to be handled. 
  2. We do not, ourselves, own any native resources.  This means we no longer need a finalizer.

These two differences eliminate the need for the protected Dispose(bool disposing) method.  If somebody forgets to dispose of us, the finalizer will ignore us, but will still finalize our LicenseAGenerator member correctly.  This means we do not need the finalizer.

Without the finalizer, we have no need to differentiate between finalization and Dispose() being called on our object, so we can put our logic directly in the Dispose() method.  If we were not sealed, or if we had native resources, we would need to implement the pattern from Part 1 or Part 2.

About Reed
Reed Copsey, Jr. - http://www.reedcopsey.com - http://twitter.com/ReedCopsey

Comments

6 Responses to “IDisposable Part 3 – Encapsulating an IDisposable class”
  1. zamesking says:

    Hi reed,

    In this case, if the user forgets to call the dispose method of AFactory, unmanaged resources of LicenseGenerator will not be released. While in pattern1 and partter2. the finalizer will call dispose(false) to dispose unmanned resource when they forget to. Will this be a problem?

  2. Reed says:

    Zamesking:

    It won’t be a problem. If AFactory is every a candidate for finalization, that means that all of its private managed resources (in this case, LicenseGenerator) will also be candidates for finalization. When LicenseGenerator’s finalizer runs, it will dispose of the unmanaged resource. There is no need for an explicit finalizer in AFactory, only in LicenseGenerator.

    This is why, when encapsulating an IDisposable, you don’t need a finalizer – even though you still want to be IDisposable, and why the pattern is differnet in this case. If you directly contain a native resource, you need a finalizer – otherwise, you typically do not need one.

  3. zamesking says:

    Reed,

    Thanks for explaining it clearly, I just forgot the purpose of the IDisposable interface. Actually, here AFactory class implements IDisposable interface to make it can be release it’s managed resources explicitly.

    Keep your good work, I decide to go through all your MVVM articles. Actually, I get to know you in msdn forums, and find you can always explaining tech in clear words, and your suggestions in the blogs are very helpful.

  4. Reed says:

    Zamesking:

    Thanks for the feedback!

    I’m glad the post is helping. The series on IDisposable was probably my favorite, up until my new MVVM one ;) Both are trying to tackle a subject that’s been talked about a lot, but take it on from a slightly different angle, in a bit more depth. I hope you find them useful.

    -Reed

  5. JCDrumKing says:

    Reed,

    Thank you very much for your commitment to the developer community.

    I am still wrangling with what to do in my particular situation…
    I have written a class that encapsulates API functionality for an external system. Creating the connection is costly — consistently takes 6 to 7 seconds to connect — so I am creating the connection in the constructor and leaving it open for the object’s brief lifetime (it is for a web application). (During its lifetime, several methods are repetitively called, and performance would be horrible if I opened and closed the connection within each method.)

    The API object does have a Disconnect() and Dispose() method and I am exposing my own Disconnect() method and implementing IDispose. Good form would be for the user of my class to always Disconnect() and Dispose(), but of course there is no way to guarantee that will happen.

    From what I’ve read, it seems I can assume that the API object itself will be disposed of on its own since it is a manged resource. Would that be correct?

    More importantly, however, I do want to be sure that connection is always explicitly closed first. Even though I have no unmanaged resources, is this a case where a destructor is definitely needed? And I assume that I would check for and close the open connection regardless of whether Dispose(bool) was called with True or False?

    If you have sample code that illustrates this scenario, that would be awesome:
    1. Class (can be sealed if that helps) with a private class-level variable that contains an open connection to something (connection made in the constructor).
    2. The Class exposes Disconnect() and implements IDispose.
    3. Code is in place to reliably ensure that the connection will be closed if the user of the class neglected to do so.

    Another thing I wonder is, do I need to implement IDispose at all? Is it dangerous/stupid to assume that the API object is smart enough to internally close the connection itself when it is disposed/finalized?

    Thank you again!

    • Reed says:

      “From what I’ve read, it seems I can assume that the API object itself will be disposed of on its own since it is a manged resource. Would that be correct?”

      Yes. If the API you’re using is written properly, you don’t need a finalizer. The reason for this is that, as soon as your “wrapper” class would be finalized, any managed references (the internal API handle) are also eligible for finalization, and the IDisposable implementation there should handle the closing automatically.

      Adding a finalizer in your class would really have no effect, and just decrease performance.

      If, however, you are finding that the connection is not being closed because the internal implementation is written improperly, you could add a finalizer and close it explicitly – but this really shouldn’t be required.

      -Reed

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!