Tuesday, September 16, 2008

What's the Difference Between Dispose() And Close()?

A Question

I was bouncing around StackOverflow the other day when a user asked an interesting question. What's the difference between calling Dispose() and calling Close()?

At first I got into a talk about Non Deterministic Finalization and told the developer that you should always call Dispose(). In fact, a lot of the time Dispose() actually calls Close(), but with Dispose() you're assured that the object is cleaning up any unmanaged resources that it would end up doing when the Garbage Collector finally came around and called Finalize() on it. I mean that's how you avoid Non Deterministic Finalization right?

But Wait, There's More

I was pretty sure I'd gotten it right and delivered some good advice when I was one upped by the post of another user. I liked his answer more and thought he went one step further in delivering a better rule of thumb. In some cases like SqlConnection, calling Dispose() actually resets the state of the object. In these cases you can call Close() more than once, but if you call Dispose() multiple times you can actually have an exception thrown. A decent rule of thumb to take away is:

  • If you are done with an object then call Dispose() on it.
  • If you are planning on reusing the object but want to temporarily free some resources then use Close().

It's worth mentioning that this is a rule of thumb, there are bound to be exceptions. You're kind of hoping that the author of these codes was on the same page as you when s/he was writing them.

Supposedly the above rule was pulled from the Framework Design Guidelines. If you really want to know what's going on then use the .NET Reflector to fill in the details. When I went thumbing through common objects that implement IDisposable, I actually found a couple classes who's Close() actually calls Dispose(), although most that I found have Dispose() methods who end up calling Close() (in addition to doing some other cleanup and suppressing finalize).

That being said all the Dispose() methods do a great job of cleanup and I would still advocate using Dispose() when you're done with the object. Consider the following popular objects that implement IDisposable.

System.Data.SQLClient.SQLConnection.Dispose()
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
}
this.DisposeMe(disposing);
base.Dispose(disposing);
}

Microsoft.SharePoint.SPWeb.Dispose()

[SharePointPermission(SecurityAction.Demand, ObjectModel=true)]
public void Dispose()
{
this.Close();
}

System.IO.StreamWriter.Dispose()

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.OutStream.Close();
}
}

In Close()ing

So that's my two cents on the whole Close() vs Dispose() topic. As long as you're thinking about your objects cleaning up after themselves you're on the right trail. While garbage collection has come leaps and bounds in the last 10 years it still needs a little help form you the developer. Remember to have your objects clean up after themselves and keep it clean.

Best,
Tyler Holmes


Keep it Clean

2 comments:

timvw said...

Unless you're using WCF, where they somewhat made a (imho) mistake.

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

Tyler Holmes said...

Nice link tim. I'll take it as a point to not call Dispose on WCF clients lest I potentially hide errors, and/or have exceptions thrown from WCF.