Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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: https://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.
- Anonymous
September 23, 2004
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. - Anonymous
September 23, 2004
The comment has been removed - Anonymous
September 23, 2004
The comment has been removed - Anonymous
September 23, 2004
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 ;-) - Anonymous
September 23, 2004
The comment has been removed - Anonymous
September 23, 2004
The comment has been removed - Anonymous
September 23, 2004
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 ;-) - Anonymous
September 23, 2004
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). - Anonymous
September 23, 2004
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? - Anonymous
September 23, 2004
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. - Anonymous
September 23, 2004
The comment has been removed - Anonymous
September 29, 2004
Describes a base class for disposable objects. - Anonymous
September 29, 2004
Describes a base class for disposable objects. - Anonymous
September 29, 2004
Describes a base class for disposable objects. - Anonymous
June 02, 2009
PingBack from http://hammockstandsite.info/story.php?id=18314 - Anonymous
June 18, 2009
PingBack from http://thestoragebench.info/story.php?id=5028 - Anonymous
April 01, 2010
No sure I agree with "Don't throw exceptions in Dispose". There are certainly places in the .net framework where this happens (e.g. disposing a faulted wcf client). I also haven't been able to find anything in the official documentation warning against this.