IDisposable Best Practices

If your code makes use of a managed resource, such as a SqlConnection, that implements IDisposable then your code has a responsibilitiy to ensure it is properly disposed of – a responsibility to implement IDisposable itself.

How we should do this is not clearly defined though it becomes obvious quite quickly that Microsoft has a definite pattern that we should be following for “Best Practice”.  It took a while, but I finally found a good explanation for this pattern here.

I’ll try to explain it here as best I can, using my own code as an example.  I have a class that implements SqlConnection as a private member variable. The code does a lot of database work and I wanted to reuse the same connection object as much as possible.  Keeping this variable inside my class however requires my code to implement the IDisposable method – to ensure its properly disposed of.

First up, and most confusingly, we are required to implement a private dispose method that takes a bool as a parameter.  This isn’t automatically added if we get visual studio to fill in the template so it has a lot of people confused.  Here is a basic implementation of this method from my example.

private void Dispose(bool disposing)
{
    if (disposing)
    {
       connection.Dispose();
       connection = null;
    }
}

Now this code takes a boolean variable called disposing.  Basically, this value determines where the dispose method was called from – there are two possible places.  The first, is the implemented Dispose() method that I will show in a moment, and the second is the class finalizer – if one exists.  If the method is called from Dispose(), then true should be passed to the it.  If its called from the finalizer, then false should be passed.

From what I can see, the difference is that calling Dispose(true) should ensure that all managed objects are disposed of. (Such as my SqlConnection object).  If Dispose(false) is called, all that should be skipped, but we should still dispose of any natively allocated resources (resources allocated using AllocHGlobal or the like.)  Native resources should be disposed of regardless of the parameter, so should be placed after the main if statement in Dispose().

Now for the example, we have no native resources and thus don’t need a finalizer.  All we need now is the Dispose() function.

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

The first statement calls dispose and makes it all happen.  The second tells the garbage collector to avoid finalizing this object – I guess to avoid calling Dispose(bool) twice.

Thats pretty much all there is to it. If you can think of anything else pertinent that i’ve missed, comments are welcome.

Advertisements

2 thoughts on “IDisposable Best Practices

  1. So if the finalizer calls Dispose(false);

    Does that mean the finalizer will impliclitly call Dispose on all the managed objects, since Dispose(false), will skip the call to

    if (disposing)
    {
    connection.Dispose();
    connection = null;
    }

    Doesn’t that mean that if the Finalizer is the one calling it, connection doesn’t get disposed, or does the Finalizer impliclity call it already?

  2. Thats right, yeah. I think the basic idea behind that is that Finalize shouldn’t be responsible for disposing of managed IDispose objects – you should be disposing of them yourself in code (by calling Dispose). What should be disposed of outside of the if statement (thus, by the finalize method) is any unmanaged resources.

    We don’t actually see a lot of those in .Net programming, they were far more common in c++ and even more common in c programming. What we’re talking about there is when you manually allocate memory, such as by using the equivalent of the malloc function (I think the .Net equiv is AllocHGlobal). If you don’t know how or why to do that, odds are you don’t need to. I’ve yet to come across a situation in which I had to do it. It makes the whole software unmanaged to a degree by granting control at a much lower level than is usual for .Net.

    Another thing to realise is that if you don’t call Dispose on your IDisposable objects, it’s not going to end the world. It’s a bad idea, and a bad habit to get into (hence the best practice here), however .Net environment garbage collection is likely to find and get it eventually. This is not necessarily the case with manually allocated memory, so that gets disposed of regardless of whether or not Dispose is called – finalize will be called when garbage collection finds the object so if your object ends up orphaned, finalize will be called, the connection object will be cut lose for garbage collection to find later, but your unmanaged code will still be disposed of.

    I’m trying to think of a reason you might want the connection object left alone when finalize is called. I guess it is possible (not in the case I was using as an example, but perhaps in others) for the connection object to be referenced in several objects. If one of those objects were orphaned and garbage collected, having it dispose of your connection object prematurely would leave your other objects in a dangerous state – referencing a null object where they expect a connection.

    Hope that makes things a bit clearer, rather than just muddying the waters further 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s