473,395 Members | 1,656 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Dispose method throwing an exception

Hi,

I have a class similar to that:

class MyClass : IDisposable {
IDisposable obj1;
IDisposable obj2;
IDisposable obj3;

MyClass() {
obj1 = new SomeDisposableClass();
obj2 = new SomeDisposableClass();
obj3 = new SomeDisposableClass();
}

void Dispose() {
obj1.Dispose();
obj2.Dispose();
obj3.Dispose();
}
}

The problem I'm having with that is that if the Dispose method of obj2
throws an exception, obj3 will not get disposed.

How would you write the Dispose method of MyClass to correctly dispose
all three objects (without swallowing the exception)?

... something like.. uh oh..:

void Dispose() {
try {
obj1.Dispose();
}
finally {
try {
obj2.Dispose();
}
finally {
obj3.Dispose();
}
}
}

thanks,
Max
Jun 14 '06 #1
5 5171
On Wed, 14 Jun 2006 22:47:55 +0200, Markus Stoeger wrote:

void Dispose() {
obj1.Dispose();
obj2.Dispose();
obj3.Dispose();
}
The problem I'm having with that is that if the Dispose method of obj2
throws an exception, obj3 will not get disposed.

How would you write the Dispose method of MyClass to correctly dispose
all three objects (without swallowing the exception)?


Dispose() should not throw any exception. This is clearly mentionned in the
IDisposable documentation. I suppose that this rule has been put in place
to solve the exact same problem you are facing now. So if your
SomeDisposableClass class follows this rule, there is no problem (you can
safely assume that this is the case for all the .NET Framework classes). If
SomeDisposableClass is a class that you've developped, review it to check
that it doesn't throw any exception. If SomeDisposableClass is a third
party class over which you have no control and you are not sure whether it
has been properly implemented in that respect, then i would do something
like:

try
{
obj1.Dispose();
}
catch {}

try
{
obj2.Dispose();
}
catch {}

and so on. You should swallow these exceptions (Dispose() is the only place
where exception swallowing is a good practice).
Jun 14 '06 #2
Mehdi <vi****@REMOVEME.gmail.com> wrote:
On Wed, 14 Jun 2006 22:47:55 +0200, Markus Stoeger wrote:
void Dispose() {
obj1.Dispose();
obj2.Dispose();
obj3.Dispose();
}


By the way, you should not implement your dispose logic directly in the
Dispose() method. Instead, follow the pattern suggested in the
documentation in which the Dispose() method suppresses the finalizer of
your class then calls the Dispose(bool) method. You should add a finalizer
to your class which also calls the Dispose(bool) method. Your dispose logic
should be placed in the Dispose(bool) method.


No. There's no need to have a finalizer unless your class directly
handles unmanaged resources. If every class which does so has a
finalizer, there's no need for classes which only hold references to
other objects to have a finalizer.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jun 14 '06 #3
On Wed, 14 Jun 2006 22:47:55 +0200, Markus Stoeger wrote:
void Dispose() {
obj1.Dispose();
obj2.Dispose();
obj3.Dispose();
}


By the way, you should not implement your dispose logic directly in the
Dispose() method. Instead, follow the pattern suggested in the
documentation in which the Dispose() method suppresses the finalizer of
your class then calls the Dispose(bool) method. You should add a finalizer
to your class which also calls the Dispose(bool) method. Your dispose logic
should be placed in the Dispose(bool) method.

Using this pattern ensures that your objects will be properly cleaned up by
the GC (thanks to the finalizer) even if the programmer forgets to call the
Dispose() method, which is essential if your class or some of its member
variables contain umanaged resources. And if the developper does call
Dispose(), the fact that Dispose() suppresses the finalizer will prevent
the GC from wasting time by putting your object in the finalization queue
even though it's been already cleaned up and will allow the GC to free the
memory used by the object immediately. If you are not familiar with
finalizers and the way the GC works, then these articles are an absolutely
essential read:
<http://msdn.microsoft.com/msdnmag/issues/1100/GCI/default.aspx>
<http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/default.aspx>
Jun 14 '06 #4
Mehdi wrote:
On Wed, 14 Jun 2006 22:47:55 +0200, Markus Stoeger wrote:

void Dispose() {
obj1.Dispose();
obj2.Dispose();
obj3.Dispose();
}

By the way, you should not implement your dispose logic directly in the
Dispose() method.


That was just a short almost-pseudo-code-like example. Normally I follow
the IDisposable pattern! :o)

thanks anyway,
Max
Jun 15 '06 #5
Mehdi wrote:
On Wed, 14 Jun 2006 22:47:55 +0200, Markus Stoeger wrote:

Dispose() should not throw any exception. This is clearly mentionned
in the IDisposable documentation. I suppose that this rule has been
put in place to solve the exact same problem you are facing now.


I couldn't find the place on msdn where they say that Dispose shouldn't
throw? See [1] in the remarks section, it says:

Dispose _can throw an exception_ if an error occurs because a resource
has already been freed and Dispose had not been called previously.

... that's at least one reason why Dispose should be allowed to throw.

If those exceptions are swallowed, it can actually lead to resource
leaks over time without anyone noticing why. No good imho.

I came up with the following simple piece of code. It does nested
try/finally blocks automatically using recursion. I think that'll do a
good job, making sure that _everything_ gets disposed without hiding the
exception in case something throws.

Call with Disposer.Dispose(obj1, obj2, obj3);

public sealed class Disposer {
private Disposer() {}

public static void Dispose(params IDisposable[] disposees) {
Dispose(disposees, 0);
}

private static void Dispose(IDisposable[] disposees, int index) {
if (index < disposees.Length) {
try {
IDisposable disposee = disposees[index];

if (disposee != null) {
disposee.Dispose();
}
}
finally {
Dispose(disposees, index + 1);
}
}
}
}

thanks,
Max

[1]
http://msdn.microsoft.com/library/de...sposetopic.asp
Jun 15 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Ken Durden | last post by:
I am in search of a comprehensive methodology of using these two object cleanup approaches to get rid of a number of bugs, unpleasantries, and cleanup-ordering issues we currently have in our...
0
by: Joe | last post by:
Reposting here as there were no useful replies in the dotnet.framework NG... What is the correct pattern for handling exceptions in IDisposable.Dispose, especially in a class that manages...
3
by: Giovanni Bassi | last post by:
Hello Group, I am running an operation in a different thread. There are resources that are released when the thread is done running. This is done at the end of the execution as it raises an...
6
by: Teresa | last post by:
1) If I do want to keep an object alive throughout the live of an application, how can I ensure that the GC doesn't clean it up? 2a) How do I determine if an object is a managed or an unmanged...
1
by: Brad Wood | last post by:
If I run this console app (outside the debugger), I will see both Console.WriteLine statements: class Program { class MyClass: IDisposable { public void Dispose() { Console.WriteLine(...
8
by: =?Utf-8?B?UGhpbGlw?= | last post by:
When is the IHttpModule Dispose driven ?....at application recycle time ? I developed a test HttpModule to trace INIT, BeginRequest, EndRequest and Dispose....and the Dispose never gets driven. ...
0
by: jeevankodali | last post by:
Hi I have a multi threaded ftp server. 2 days back it threw an exception: System.IO.IOException: The specified network name is no longer available. at System.IO.__Error.WinIOError(Int32...
5
by: jobs | last post by:
re: try catch finally to close and dispose, but still want Application_error to fire 1. If catch an exception to to dispose and close of a ado connect, how can I allow the exception to still...
19
by: rbrowning1958 | last post by:
Hello, I am confused by dispose etc. and hope someone can set me right. 1. The Dispose(Bool) the IDE generates for a form has nothing to do with IDisposable, right? 2. So when is this called?...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.