110
votes

When would I implement IDispose on a class as opposed to a destructor? I read this article, but I'm still missing the point.

My assumption is that if I implement IDispose on an object, I can explicitly 'destruct' it as opposed to waiting for the garbage collector to do it. Is this correct?

Does that mean I should always explicitly call Dispose on an object? What are some common examples of this?

7
Indeed, you should call Dispose on every Disposable object. You can do that easily using the using construct.Luc Touraille
Ah, that makes sense. I had always wondered why the 'using' statement was used for file streams. I know it had something to do with the scope of the object, but I didn't put it in context with the IDisposable interface.Jordan Parmer
One important point to remember is that a finalizer should never access any managed members of a class, as those members may no longer be valid references.Dan Bryant

7 Answers

139
votes

A finalizer (aka destructor) is part of garbage collection (GC) - it is indeterminate when (or even if) this happens, as GC mainly happens as a result of memory pressure (i.e. need more space). Finalizers are usually only used for cleaning up unmanaged resources, since managed resources will have their own collection/disposal.

Hence IDisposable is used to deterministically clean up objects, i.e. now. It doesn't collect the object's memory (that still belongs to GC) - but is used for example to close files, database connections, etc.

There are lots of previous topics on this:

Finally, note that it is not uncommon for an IDisposable object to also have a finalizer; in this case, Dispose() usually calls GC.SuppressFinalize(this), meaning that GC doesn't run the finalizer - it simply throws the memory away (much cheaper). The finalizer still runs if you forget to Dispose() the object.

27
votes

The role of the Finalize() method is to ensure that a .NET object can clean up unmanaged resources when garbage collected. However, objects such as database connections or file handlers should be released as soon as possible, instead on relying on garbage collection. For that you should implement IDisposable interface, and release your resources in the Dispose() method.

9
votes

The only thing that should be in a C# destructor is this line:

Dispose(False);

That's it. Nothing else should ever be in that method.

9
votes

There is a very good description on MSDN:

The primary use of this interface is to release unmanaged resources. The garbage collector automatically releases the memory allocated to a managed object when that object is no longer used. However, it is not possible to predict when garbage collection will occur. Furthermore, the garbage collector has no knowledge of unmanaged resources such as window handles, or open files and streams.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector. The consumer of an object can call this method when the object is no longer needed.

5
votes

Your question regarding whether or not you should always call Dispose is usually a heated debate. See this blog for an interesting perspective from respected individuals in the .NET community.

Personally, I think Jeffrey Richter's position that calling Dispose is not mandatory is incredibly weak. He gives two examples to justify his opinion.

In the first example he says calling Dispose on Windows Forms controls is tedious and unnecessary in mainstream scenarios. However, he fails to mention that Dispose actually is called automatically by control containers in those mainstream scenarios.

In the second example he states that a developer may incorrectly assume that the instance from IAsyncResult.WaitHandle should be aggressively disposed without realizing that the property lazily initializes the wait handle resulting in an unnecessary performance penalty. But, the problem with this example is that the IAsyncResult itself does not adhere to Microsoft's own published guidelines for dealing with IDisposable objects. That is if a class holds a reference to an IDisposable type then the class itself should implement IDisposable. If IAsyncResult followed that rule then its own Dispose method could make the decision regarding which of its constituent members needs disposing.

So unless someone has a more compelling argument I am going to stay in the "always call Dispose" camp with the understanding that there are going to be some fringe cases that arise mostly out of poor design choices.

3
votes

It's pretty simple really. I know it's been answered but I'll try again but will try to keep it as simple as possible.

A destructor should generally never be used. It is only run .net wants it to run. It will only run after a garbage collectoin cycle. It may never actually be run during the lifecycle of your application. For this reason, you should not ever put any code in a destructor that 'must' be run. You also can't rely on any existing objects within the class to exist when it runs (they may have already been cleaned up as the order in which destructors run in is not garanteed).

IDisposible should be used whenever you have an object that creates resources that need cleaning up (ie, file and graphics handles). In fact, many argue that anything you put in a destructor should be putin IDisposable due to the reasons listed above.

Most classes will call dispose when the finalizer is executed but this is simply there as a safe guard and should never be relied upon. You should explicitly dispose anything that implements IDisposable when you're done with it. If you do implement IDisposable, you should call dispose in finalizer. See http://msdn.microsoft.com/en-us/library/system.idisposable.aspx for an example.

0
votes

Here is another fine article which clears up some of the mist surrounding IDisposable, the GC and dispose.

Chris Lyons WebLog Demystifying Dispose