Welcome to MSDN Blogs Sign in | Join | Help

Dispose Dos and Don'ts

Due to the positive response on my previous entry on Dispose, I thought I'd write another, this time on what one should and shouldn't do with a Dispose method.

  • Dispose should contain code to release any unmanaged resources associated with the object's instance. For example, any handles should be released, database connections closed, etc. This simulates deterministic finalization by letting the developer do the resource cleanup when he/she is done with the object. You may want to use an IsDisposed bool and check it inside Dispose.
  • Dispose should be safely callable multiple times. In my example above, if some user of your class called Dispose twice, we would crash with an unhandled InvalidOperationException trying to “double free” the GCHandle.
  • If you inherit from an IDisposable object, call the base class' Dispose method. Unlike finalizers, which the GC calls, Dispose is only called by user code (sometimes automatically in C#, as I covered previously). This means any unmanaged resources held by your object's parent, must also be disposed of.
  • Suppress finalization in Dispose. There has been some debate about whether GC.SuppressFinalization(this) should go before or after the cleanup code. Some argue after, in case something goes wrong before you've finished cleaning up. Others argue before, otherwise you may open up a race condition between your finalizer and your Dispose method. You should consider both strategies depending on your object's implementation.
  • Don't throw exceptions in Dispose. Nothing should go wrong with your object calling Dispose. Mainly for reasons stated above.
  • Throw ObjectDisposedException if a caller tries to use a released resource. You may be in a situation where you've disposed of your object because you no longer need the unmanaged resource, but you still need to have the object hanging around. If this is the case, any methods that would normally access the resource should throw an ObjectDisposedException, while other (possibly useful) methods should not.
  • Don't call Dispose from one thread, while still using the object on another. Try to make the thread that created the object be the one that disposes of it. This is more general good multithreaded programming advice, then Dispose specific.
  • Whenever possible, follow the Dispose Pattern. That link, one more time: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconfinalizedispose.asp.

If you have any other Dispose Do's and Don'ts, please post them in the comments.

Published Thursday, September 23, 2004 9:50 AM by clyon
Filed under:

Comments

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 9:58 AM by Richard Blewett
In terms of ObjectDisposedException I'd argue that you should *always* throw it after a client has called Dispose (other than recalling the Dispose method). They don't know which methods access a resource you release and which don't (unless they have an uhealthy knowledge of your implementation).

Dispose to me means "I'm finished with you". So in that case they have no business calling your methods beyond that point.

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:21 AM by Chris Lyon
Hi Richard

You could imagine a class that has a property like IsClosed, or a static method that you wouldn't want to throw. Also consider inherited methods (in particular methods that inherit from System.Object, like ToString()).

I hesitate to lay down "always do it this way..." rules, because there are always exceptions.

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:22 AM by Richard Blewett
How could you end up in a race condition between the finalizer and dispose? If dispose is running, someone needs to have called it - presumable from a live root. So unless the GC has made a catastrophic error and decided you were garbage when you had a live root; or another object called your Dispose in their Finalizer (which they definitely shouldn't) - how is the Finalizer going to be running at the same time as Dispose?

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:25 AM by Richard Blewett
OK - granted about statics - I wouldn't consider statics anyway as they are not involved with the instance being Disposed. But I guess the IsClosed is valid. I suppose I prefer to lay down an absolute and then let people argue why their situation is different ;-)

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:25 AM by Chris Lyon
Richard, please read the comments from my previous blog entry and the links to Chris Brumme's blog for an explanation on this race condition.

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:32 AM by Chris Lyon
Richard, you probably don't want to throw inside overloaded operators or methods inherited from interfaces, just to name a few more examples.

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:38 AM by Richard Blewett
Ugghh - Resurrection

Is there actually a useful purpose for resurrection? I have to say its always looked like an abomination to me and so never really been that bright on my radar.

I find it slightly perverse to prefer guarding against someone resurrecting my object than against protecting against clean up failure in Dispose. To me the latter is a much more likely scenario and anyone resurrecting my object deserves everything they get ;-)

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:41 AM by Chris Lyon
It's clear to me now that I need to dedicate a whole blog entry on resurrection :)

Unless resurrection is an expected scenario, guarding against it isn't really necessary (most BCL classes don't).

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 10:53 AM by Richard Blewett
Chris, I can kind of see why throwing in an operator overload would be bizarre for a consumer, but why do you say an interface implementation? What if that implementation accesses the released resource?

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 11:00 AM by Chris Lyon
Interfaces generally specify behaviour, not implementation, so the Interface is often seperate from the resource.

For example, IClomparable.CompareTo shouldn't necessarily throw if the object has been disposed of.

Again, these are guidelines, not hard rules.

# re: Dispose Dos and Don'ts

Thursday, September 23, 2004 1:52 PM by Richard Blewett
Agreed that interface define behaviour, but the issue is whether the implementation can satisfy that behaviour once Dispose has been called. But as you say - they are only guidelines (have you seen Pirates of the Caribbean? ;-) )

I'm looking forward to your blog post on resurrection - it will be interesting to here about the BCL classes that have been built with it in mind.

# Dispose Do's and Don'ts

Monday, September 27, 2004 10:08 PM by OdeToCode Link Blog

# Disposable Object

Thursday, September 30, 2004 6:51 AM by Managed from down under
Describes a base class for disposable objects.

# Disposable Object

Thursday, September 30, 2004 6:52 AM by Managed from down under
Describes a base class for disposable objects.

# Disposable Object

Thursday, September 30, 2004 6:53 AM by Managed from down under
Describes a base class for disposable objects.

# More on Garbage Collection

Saturday, October 02, 2004 1:57 PM by Rob Windsor's Weblog

# Chris Lyon s WebLog Dispose Dos and Don ts | Hammock Stand

# Chris Lyon s WebLog Dispose Dos and Don ts | storage bench

Anonymous comments are disabled
 
Page view tracker