Proper use of inner exceptions

  • Thread starter Thread starter Kenny Cutter
  • Start date Start date
K

Kenny Cutter

Hi group,

I am quite new to exceptions in .NET and I am a bit confused of how to
use the inner exceptions. Could anyone explain? Let's say I have a
function that takes a double (X) that is not supposed to be less or
equal to zero. Let's call this function DoSomething.

Also let's say that this function in turn calls another function doing
something with X.

Then if there is a bug in the DoSomething function that causes the
other function to throw an ArgumentOutOfRangeException.

void DoSomething(double X)
{
if(X<=0)
throw new ArgumentOutOfRangeException("X","X has to be greater
than zero");
X-=10; // This is a bug..
AnotherFunction(X);
}

void AnotherFunction(double X)
{
if(X<=0)
throw new ArgumentOutOfRangeException("X"," X has to be
greater than zero ");
 
Kenny,
Ok, now if I call DoSomething with 10 or less I will get an
ArgumentOutOfRangeException. Then I will think that this is because I
called DoSomething with a value of X less or equal to zero.

Not if you examine the exception's StackTrace, it will tell you that
it originated from AnotherFunction.



Mattias
 
IMO :
- there is no need to try to catch this situation, just correct the bug
- if DoSomething requires x<=0 because it calls AnotherFunction that
requires x<=0, don't catch the exception in DoSomething. IMO the exception
just be thrown exactly where your requirement is no met.
- an exception is to catch programming or environment error. Here I would
validate the user input before calling the function.

Patrice


--
 
Hello Kenny,

There have been a few online articles and blogs on "best practices" in .Net
exception handling, so I'd suggest you start there.
This topic has been discussed here many times before.

In a nutshell:
a) catch the error as close to the point where it triggered as possible,
b) log the event
c) respond appropriately so no system state is corrupted or memory is lost,
d) then, if the downstream error means that your current method cannot
perform its responsibilities in a way that gracefully handles the error, you
return a new exception containing the old one as an inner exeption.

80% of the time, you will not create a new exception to contain the old one.
Also, it is perfectly OK to throw a new ApplicationException() containing
your embedded exception... you don't need to create a custom exception class
for every possible exception. (If you have an entire "class" of exceptions,
then you can benefit from the custom exception type).

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
 
Kenny,

Nick Malik is right: there are a lot of 'blog articles, online
whitepapers, and even books on the subject of properly handling
exceptions. Here are a few places to start:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp08162001.asp

http://msdn.microsoft.com/msdnmag/issues/04/06/NET/default.aspx

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp

However, all of this won't stop me from adding my two cents' worth. :)
The philosophy you stated in your opening question is along the right
lines. To my thinking, the purpose of inner exceptions is to transform
exceptions that you know may happen in your method into terms that make
sense to callers.

For example, if you were to require that your argument X be non-zero,
because your method is going to try to divide by X, it would be very
bad form to simply let the method throw a DivideByZeroException. From
the caller's point of view, this is meaningless. The caller has to
understand the inner workings of your method in order to interpret the
exception.

Now, whether you choose to test for X == 0 and throw an
InvalidArgumentException, or catch the DivideByZeroException and wrap
it in an InvalidArgumentException is up to you. Most people would do
the former, but you could do the latter if the information about where
the divide by zero happened was of interest and you didn't want to lose
it.

In cases in which you call other methods that throw exceptions, you may
have no choice but to catch them, and then you may wish to transform
them into terms more meaningful to your callers. In these cases you
almost certainly want to wrap them as inner exceptions.
 
Not to put too fine a point on it:
a double divided by a double won't throw a DivideByZeroException...
 
Hi.

I have the same kind of questions as Kenny.
Anyone got some more useful links to help me learn how to properly
handle exceptions.
A link to a good discussion in the subject would be nice.
 
There have been a few online articles and blogs on "best practices" in
.Net
exception handling, so I'd suggest you start there.
This topic has been discussed here many times before.

In a nutshell:
a) catch the error as close to the point where it triggered as possible,
b) log the event

Usually a good idea, but this may not be the correct action to take - it
depends on the system. The issue of where logging should occur needs to
account for intermediate routines that catch-wrap-throw. You would not want
intermediate catch blocks to also log the exception - it would quickly
overwhelm the logging system with redundant data. I prefer to log it once at
the original exception site, and then log it again at a boundary across
which the exception will propagate. I usually define the boundary as the
edge of a web service, process or appdomain.
c) respond appropriately so no system state is corrupted or memory is
lost,

Easier said then done. Implementing complete rollback semantics across all
objects, external data stores, etc. is non-trivial - in some cases it may
not even be possible. These potential corruption points should be defined
and known.
d) then, if the downstream error means that your current method cannot
perform its responsibilities in a way that gracefully handles the error,
you
return a new exception containing the old one as an inner exeption.

80% of the time, you will not create a new exception to contain the old
one.
Also, it is perfectly OK to throw a new ApplicationException() containing
your embedded exception... you don't need to create a custom exception
class
for every possible exception.

As an alternative to using the generic ApplicationException you can throw
the same exception type as the that was caught (clone it). Also, the use of
the ApplicationException type is being discouraged by new MSFT guidelines.

There has also been discussions around the distinction between technical
exceptions and business logic exceptions. Typical usage is for low-level
code to either handle faults or propagate technical exceptions upwards, and
higher level logic then provides a translation layer that maps these into
business logic exceptions that are more understandable to users. In other
words, presenting a user with a null reference exception doesn't help them
much - telling them to enter a valid user name does.
(If you have an entire "class" of exceptions,
then you can benefit from the custom exception type).

There are downsides, mainly with versioning and system evolution, and
propagating exceptions across process boundaries. I would discourage
allowing a custom exception to propagate outside of a web service - the
client may not be able to deserialize it. This may not be an issue for
small, self-contained systems, but for distributed systems, either using web
services, remoting, or multiple appdomains, it can be a problem.
 
Back
Top