Bubbling up exceptions

P

pamelafluente

Hi guys,

When bubbling some exception up to some interface handlers

- what is most recommandable:

Try
'some code
Catch ex As Exception
Throw
End Try
or

Try
'some code
Catch ex As Exception
Throw ex
End Try
?

- What about I just to want to add some comments in the error message,
BUT
I want to keep ALL the inner exceptions (so that I can recursively
spit them to the
user when I arrive up to the UI ) How do I do that correctly ?

- And, is it true that anything after a Throw will be in any case
ignored ?

-P
 
D

Dave Sexton

Hi,
When bubbling some exception up to some interface handlers

- what is most recommandable:

Try
'some code
Catch ex As Exception
Throw
End Try
or

Try
'some code
Catch ex As Exception
Throw ex
End Try

I'm not a VB programmer but I don't think that the first example should even compile. If it does, then I assume that the behavior
of each sample is identicial and in that case choose whichever you like better :)
- What about I just to want to add some comments in the error message,
BUT
I want to keep ALL the inner exceptions (so that I can recursively
spit them to the
user when I arrive up to the UI ) How do I do that correctly ?

If you want to display information to the UI when you catch an exception then just do it. Don't rethrow the Exception. Only
rethrow the exception if it cannot be handled by your code. In that case, you can wrap the exception with another exception that
provides some more information about the error. The second argument supplies the InnerException for the new Exception:

Throw new Exception("An error occurred in method X trying to perform operation Y. Variable A at the time was: " & A, ex)

Also, don't just catch Exception everywhere. There are certain Exceptions in the framework that you won't be able to handle in code
and should not be caught. For this reason you should only catch those Types of exceptions that can be handled by your code.

For instance, if you are performing some operation on the System.IO.File object in your Try...Catch block then you could catch
System.IO.IOException if and only if that exception can be handled gracefully by your code. Graceful means that the state of your
program will not be corrupt, or that it can be fixed before returning to the caller. You could also update the UI, for instance,
with a simple message like "Cannot save data to file: " & ex.Message. There is no need to rethrow the IOException since it has been
handled gracefully by your code.
- And, is it true that anything after a Throw will be in any case
ignored ?

Yes, anything after a Throw statement within the same method body will not be executed.
 
P

pamelafluente

Dave Sexton ha scritto:
Hi,


I'm not a VB programmer but I don't think that the first example should even compile. If it does, then I assume that the behavior
of each sample is identicial and in that case choose whichever you like better :)

Thanks Dave. [Actually I posted here by error. Sorry. The message was
for the VB group.]

Anyway, on this point I have been confused by some statement in this
article:
http://www.codeproject.com/dotnet/exceptionbestpractices.asp

where the author says that
Throw ex
is wrong and I should always use
Throw

So I 'd like to hear opinions on that.... Thank you :)

-P
 
D

Dave Sexton

Hi,
where the author says that
Throw ex
is wrong and I should always use
Throw

Throw without ex, at least in C#, is used when you do not assign the exception to a variable:

try
{
// do something
}
catch // no variable assignment
{
throw; // throw exception in current scope
}

I'm not sure if there is an equivalent in VB.

In C# the following code actually does compile by assuming that throw refers to the exception caught in the current scope, just like
in the code above. This works regardless of whether it is assigned to a variable.

That code will function exactly as "Throw ex" in your other example. I don't think it matters which one you choose.

--
Dave Sexton

Dave Sexton ha scritto:
Hi,


I'm not a VB programmer but I don't think that the first example should even compile. If it does, then I assume that the
behavior
of each sample is identicial and in that case choose whichever you like better :)

Thanks Dave. [Actually I posted here by error. Sorry. The message was
for the VB group.]

Anyway, on this point I have been confused by some statement in this
article:
http://www.codeproject.com/dotnet/exceptionbestpractices.asp

where the author says that
Throw ex
is wrong and I should always use
Throw

So I 'd like to hear opinions on that.... Thank you :)

-P
 
L

Laurent Bugnion

Hi,

Thanks Dave. [Actually I posted here by error. Sorry. The message was
for the VB group.]

Anyway, on this point I have been confused by some statement in this
article:
http://www.codeproject.com/dotnet/exceptionbestpractices.asp

where the author says that
Throw ex
is wrong and I should always use
Throw

So I 'd like to hear opinions on that.... Thank you :)

-P

First, the CodeProject example is in C#, where "throw;" is legal. I am
not sure if it is in VB.NET.

In C#, the idea to use "throw;" instead of "throw ex;" is, as explained
in the article, to avoid modifying the stack trace.

Every exception object has a stack trace, which allows you to see where
it comes from. It is a string representation of the call stack at the
time where the exception was thrown.

However, when you do "throw ex;", it clears the stack trace and
everything appears as if the exception was thrown from there.

Consider the following code:

private void ExecuteThrow()
{
try
{
NestedMethod1();
}
catch ( Exception )
{
Console.WriteLine( "Exception caught" );
throw;
}
}

private void ExecuteThrowEx()
{
try
{
NestedMethod1();
}
catch ( Exception ex )
{
Console.WriteLine( "Exception caught" );
throw ex;
}
}

private void NestedMethod1()
{
NestedMethod2();
}

private void NestedMethod2()
{
NestedMethod3();
}

private void NestedMethod3()
{
throw new ArgumentException( "This is a dummy exception only" );
}

If I call ExecuteThrow, the stack trace is the following:

at temp.NestedMethod3() in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 77
at temp.NestedMethod2() in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 72
at temp.NestedMethod1() in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 67
at temp.ExecuteThrow() in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 48
at temp.bnExecute_Click(Object sender, EventArgs e) in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 26

If I call ExecuteThrowEx, the stack trace is:

at temp.ExecuteThrowEx() in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 61
at temp.bnExecute_Click(Object sender, EventArgs e) in
d:\GalaSoft\myhtml\GalaSoft\_current\temp.aspx.cs:line 30

I lost the whole path to NestedMethod3. That's the idea in this article.

HTH,
Laurent
 
L

Laurent Bugnion

Hi,

Dave said:
Hi,


In C# the following code actually does compile by assuming that throw refers to the exception caught in the current scope, just like
in the code above. This works regardless of whether it is assigned to a variable.




That code will function exactly as "Throw ex" in your other example. I don't think it matters which one you choose.

In C# it is not the same. Check my post about that in this same thread.

Greetings,
Laurent
 
D

Dave Sexton

Hi Laurent,

I see the difference now, thanks.

Code "throw" without explicitly specifying an exception so that the exception in scope is rethrown and the stack trace is preserved.
If you need to wrap the exception, however, you have no choice but to include the in-scope exception as the InnerException and the
stack trace will be rebuilt.

As a rule of thumb, I don't normally catch and rethrow without wrapping the exception. If you have nothing more to add to it then
don't catch it in the first place. The exception to that rule is if you need to log something or perform some state management when
the exception occurs, in which case using "throw" to rethrow the exception is good advice.
 
L

Laurent Bugnion

Hi,

Dave said:
Hi Laurent,

I see the difference now, thanks.

Code "throw" without explicitly specifying an exception so that the exception in scope is rethrown and the stack trace is preserved.
If you need to wrap the exception, however, you have no choice but to include the in-scope exception as the InnerException and the
stack trace will be rebuilt.

Only the stack trace of the outer exception will start at the moment
where the outer exception is thrown. The stack trace of the
InnerException will be preserved. That's why you should include it when
you build your own exceptions

catch ( Exception ex )
{
// Do something
throw new MyOwnException( "message", ex );
}

As a rule of thumb, I don't normally catch and rethrow without wrapping the exception. If you have nothing more to add to it then
don't catch it in the first place. The exception to that rule is if you need to log something or perform some state management when
the exception occurs, in which case using "throw" to rethrow the exception is good advice.

HTH,
Laurent
 
P

pamelafluente

Laurent Bugnion ha scritto:

Thank you Laurent and Dave.

*Very* helpful and instructive discussion.

-P
 
P

pamelafluente

"without amnesia" ? :)

Actually, more than simple amnesia, it would be an unrecoverable loss
of memory :))

Very cute Laurent !!

Ciao,

-P

Laurent Bugnion ha scritto:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top