Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is IDisposable implementation designed the way it is [closed]

Tags:

c#

.net

Let's take a look at the infamous IDisposable interface:

[ComVisible(true)]
public interface IDisposable
{
    void Dispose();
}

and a typical implementation, as recommended by MSDN (I omitted the check if current object has already been disposed):

public class Base : IDisposable
{
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // release managed
        }
        // release unmanaged
        disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~Base()
    {
        Dispose(false);
    }
}

public class Derived : Base
{
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            // release managed
        }
        // release unmanaged
        disposed = true;
    }
}

Problem is: I think this implementation is counter-intuitive. And it is also significantly different in base and derived class. Derived class is supposed to assume that base class implemented IDisposable properly and then override Dispose(bool), which is not even a part of the original interface.

I have to admit, I came up with this question because I usually ask junior programmers to implement IDisposable on a job interview. If they don't exactly know how it's supposed to be done, they come up with something close to this:

public class Base : IDisposable
{
    public virtual void Dispose()
    {
        // release managed and unmanaged
        GC.SuppressFinalize(this);
    }

    ~Base()
    {
        // release unmanaged
    }
}

public class Derived : Base
{
    public override void Dispose()
    {
        // release managed and unmanaged
        base.Dispose();
    }

    ~Derived()
    {
        // release unmanaged
    }
}

To me, this implementation is more clear and more consistent. Of course, the bad thing is that we have to release unmanaged resources in two different places, but the important point is that probably over 99% custom classes do not have anything unmanaged to dispose, so they won't need a finalizer anyway. I can't explain to a junior programmer why MSDN implementation is better because I don't really understand it myself.

So I'm wondering, what led to such unusual design decisions (making derived class to override a different method than the one in the interface and making him think about unmanaged resources which it most probably doesn't contain). Any thoughts on this matter?

like image 651
Chriso Avatar asked Jan 25 '10 18:01

Chriso


1 Answers

The answer to this and most other API design questions can be found in this book.

Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries http://www.amazon.com/gp/product/0321545613?ie=UTF8&tag=bradabramsblo-20&link_code=wql&camp=212361&creative=380601

This is literally the set of rules Microsoft employees use to build .NET APIs. The rules are free (see below), but the book has the commentary that explains the rules. It really is a must have for .NET developers.

http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx

like image 184
Jonathan Allen Avatar answered Oct 12 '22 12:10

Jonathan Allen