I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

July 22, 2004

Rethrowing Exceptions

There's a bit more subtlety to rethrowing exceptions than most developers realize. Although this topic is covered very nicely at The .NET Guy blog, here's another example:

        Try
            session = smgr.getSession(_strDocbaseName)
        Catch ex As Exception
            If ex.Message.IndexOf("authentication failed") > 0 Then
                Throw New Exception("more info about the exception", ex)
            Else
                Throw
            End If
        End Try

The important thing here is to preserve the call stack, and that means

  1. when throwing your more-informative exception, include the original exception as the InnerException (second parameter) for reference
  2. when you decide you can't handle the exception, re-throw the original exception as is.
Even the documentation for Throw does not document the fact that you can call Throw without any params to re-throw the current exception. Not a big deal, since

Throw ex

... would do the same thing, but less code is almost always better, IMO.

So then the next natural question that most developers ask is, "When should I catch exceptions"? And it's a very good question. Here are some guidelines that I have found useful.

  1. Unless you have a very good reason to catch an exception, DON'T. Exceptions are supposed to be exceptional, just like the dictionary meaning: uncommon, unusual. When in doubt, let the calling routine, or the global exception handler, deal with it. This is the golden rule. The hardest kinds of exceptions to troubleshoot are the ones that don't even exist, because a developer upstream of you decided to consume it.
  2. If you can correct the problem implied by the exception. For example, if you try to write to a file and it is read-only, try removing the read-only flag from the file. In this case you handled the exception and fixed the problem, so you should eat the exception. It doesn't exist, because you fixed it.
  3. If you can provide additional information about the exception. For example, if you fail to connect via HTTP to a remote website, you can provide details about why the connection failed: was the DNS invalid? Did it time out? Was the connection closed? Did the site return 401 unauthorized, which implies that credentials are needed? In this case you want to catch the exception, and re-throw it as an inner exception with more information. This is a very good reason to catch an exception, but note that we are still re-throwing it!
  4. Always try to catch specific exceptions. Avoid catching System.Exception whenever possible; try to catch just the specific errors that are specific to that block of code. Catch System.IO.FileNotFound instead.
There are, of course, times when you'll want to violate these rules for completely legitimate reasons-- but at least consider them before you do.

Posted by Jeff Atwood    View blog reactions

 

« Go, Monkey! DEVELOPERS^3 »

 

Comments

Clarification:

Throw ex

does NOT preserve the existing exception call stack (eg the stack will start with this line of code)

Throw

DOES preserve the existing exception call stack (eg this code will not appear anywhere in the stack)

Very important!

Jeff Atwood on February 16, 2005 01:27 AM

Throw and Throw ex are not the same thing :)
http://www.tkachenko.com/blog/archives/000352.html
http://www.dotnetdevs.com/advice/RethrowingExceptions.aspx

Niktu on April 3, 2006 04:45 AM

> In .Net however, when you do "throw ex;", ex is being re-thrown, but the original stack trace info gets overriden.

Niktu, that's exactly what I clarified in the comment above from Feb 2005..

Jeff Atwood on April 3, 2006 09:20 AM

Ah, yes ...

But did You point it out that using "Throw" doesn't yeld exactly same results as not catching exception in first place?
(in call stack the line number from try block generating exception gets replaced by line number of "Throw" statement - that could be significant loss of information if you happen to call same metod in multiple places of that try block ... as you could read in comments of my first link :)

Niktu on July 11, 2006 03:18 AM







(hear it spoken)


(no HTML)




Content (c) 2008 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.