Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / General / January 2005

Tip: Looking for answers? Try searching our database.

Proper use of inner exceptions

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Kenny Cutter - 18 Jan 2005 09:24 GMT
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 ");
    .
    .
    // Do something with X
}

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.

try
{
  double x= getValueFromUser();
  DoSomething(X);
}
catch(ArgumentOutOfRangeException e)
{
  MessageBox.Show("Dear User, please enter a value greater than 0");
}

But the problem here was not the input from the user but the bug in
DoSomething...

So what is the correct use of exceptions/innerexceptions? Should I
instead change the DoSomething to catch exceptions and rethrow them as
inner exceptions in an own exception type? Like this?

void DoSomething(double X)
{
    if(X<=0)
       throw new ArgumentOutOfRangeException("X","X is to small");
    X-=10;   // This is a bug..
    try
    {
       AnotherFunction(X);
    }
    catch(ArgumentOutOfRangeException e)
    {
       MyOwnException myex = new MyOwnException("Call to
       AnotherFunction failed",e);  // Set innerexception as e
    }
}

or should I catch all exceptions that AnotherFunction could throw
(catch the exceptions base type) and rethrow them as my own exception
with the innerexception set to the original exception?

Does this mean that in all assemblies that I write, in all public
functions, I should catch all exceptions and rethrow them as my own
exceptions with the innerexceptions set to the original exception? Or
have I missed something here, is there another approach to avoid the
problem above?

Any help to make me see this clearer is highly appreciated.

/kenny
Mattias Sj?gren - 18 Jan 2005 09:47 GMT
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

Signature

Mattias Sjögren [MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Patrice - 18 Jan 2005 10:02 GMT
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

> Hi group,
>
[quoted text clipped - 78 lines]
>
> /kenny
Nick Malik [Microsoft] - 18 Jan 2005 15:23 GMT
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).

Signature

--- 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.
--

> Hi group,
>
[quoted text clipped - 78 lines]
>
> /kenny
David Levine - 20 Jan 2005 12:13 GMT
> There have been a few online articles and blogs on "best practices" in
> .Net
[quoted text clipped - 4 lines]
> 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,
[quoted text clipped - 7 lines]
> 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.
Bruce Wood - 18 Jan 2005 17:41 GMT
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/cs
harp08162001.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/exce
ptdotnet.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.
scott - 19 Jan 2005 20:59 GMT
Not to put too fine a point on it:
a double divided by a double won't throw a DivideByZeroException...
Ola - 20 Jan 2005 09:15 GMT
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.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.