My musings about .NET and what not

Friends Don’t Let Friends catch (Exception)

Catching Exception, SystemException, or ApplicationException; or coding empty catch blocks, aren’t simply "bad practices" — it’s just plain wrong. Here's why you shouldn't do it.


I am inspired to share my thoughts on this for a couple of reasons. One is in response and as a follow up to my friend Justin Etheredge’s recent post over at CodeThinked, where he briefly touches on this topic, but didn’t really dive too deeply into the wheres and whys. Second is to shamelessly plug my latest Wrox e-book just released today ;-), Robust ASP.NET Exception Handling (ISBN 978-0-470-50367-6), in which I examine this and other related topics in far more depth than I will in this post.

It is common to see developers trying to “overdo it” when it comes to catching exceptions. They reason (quite understandably) that any code could potentially throw an exception. Therefore, to be on the safe side, they attempt to wrap as much of their code as possible in try statements, then catch any exception that is thrown.

Of course, it is true that an exception can be thrown from nearly any code at any time. For example, even when calling very safe-looking code, the computer might suddenly run out of memory, which throws an OutOfMemoryException. Ask yourself — would you know how to handle an OutOfMemoryException in code? Me neither! Since there is absolutely nothing you can do about those kinds of errors, there is no point in catching them in the first place.

This should point out the futility of catching very general exceptions such as System.Exception or System.SystemException, or using a catch statement without an argument (sometimes called a general catch block). These constructs are shown below.

catch (Exception)
{
   // handling code here
}
 
catch ()
{
   // handling code here
}
 
catch
{
   // handling code here
}

The third example is particularly insidious, as the MSIL generated by the C# compiler becomes catch(Object), which also catches COM and other non-CLR exceptions.

Though you may see this done in blogs and code samples from time to time (it’s very common on MSDN), these samples are usually for illustrative purposes only, and shouldn’t be used in production code, period. Remember, a general catch block catches any and every exception that occurs — even catastrophic system failures over which you have no control.

Blindly catching exceptions everywhere, or catching every possible exception, is a very bad practice, indeed. Remember, the MSDN documents all exceptions that can be directly thrown from methods and constructors in the .NET base class library. Use this as a guide in determining what exceptions might be thrown. Then, think about which specific exceptions you should catch, and why. Finally, develop a strategy to handle those specific exceptions, given the context in which it they are thrown.

There are legitimate reasons for handling exceptions. Among these are:

  • Notifying the user, and if appropriate, allowing them to retry the operation
  • Wrapping the exception in a new exception, appending additional relevant detail
  • Wrapping a specific exception in a more general exception to prevent revealing sensitive details, such as exceptions thrown from a Web service
  • Logging and/or notifying system administrators of the exception, and rethrowing it. (Even then, it’s generally not useful to routinely log handled exceptions unless you’ve got a good reason.)
  • Using a finally block to clean up resources that might be abandoned if an exception occurs

If you don’t have a reason to catch an exception, or have no idea what you would do with it if you did, then don’t. Let it bubble up the call stack, and let your application-level exception handler take care of it. After all, that’s what it’s there for.

Only catch exceptions that you are prepared to handle.

The bottom line here is that well-written code should actually contain relatively few try-catch blocks.

I hope you’ll remember this the next time you’re tempted to catch(Exception). And don’t forget to tell your friends. ;-)

Subscribe to this blog for more cool content like this!

kick it on DotNetKicks.com

shout it on DotNetShoutOut.com

vote it on WebDevVote.com

Bookmark / Share

    » Similar Posts

    1. Integrating Exception Handling Into the Development Cycle
    2. Defensive Programming, or Why Exception Handling Is Like Car Insurance
    3. If At First You Don’t Succeed - Retrying Mail Operations in .NET

    » Trackbacks & Pingbacks

    1. Thank you for submitting this cool story - Trackback from DotNetShoutout

      Friends Don’t Let Friends catch (Exception) — May 19, 2009 11:59 PM
    2. Pingback from Reflective Perspective - Chris Alcock

      Reflective Perspective - Chris Alcock — May 20, 2009 2:13 AM
    3. Pick of the week: IP and Non-Competes for Employees General Visual Studio 2010 Beta 1 : Go get the first beta of the next version of Visual Studio! Microsoft Set To Announce Commercial Availability of Windows Azure at PDC This Year : Alin Irimie has some

      Weekly Web Nuggets #65 — May 26, 2009 10:25 AM
    4. Pingback from Link Love | Kaeli's Space

      Link Love | Kaeli's Space — June 7, 2009 6:48 AM
    5. Mail sent from your application didn’t go through? Don’t give up so easily! The majority of mail server interruptions are very temporary in nature, lasting only a few seconds. Instead of failing right away, why not give your SMTP client another

    6. Pingback from Twitter Trackbacks for Friends Don???t Let Friends catch (Exception) : LeeDumond.com [leedumond.com] on Topsy.com

      Twitter Trackbacks for Friends Don???t Let Friends catch (Exception) : LeeDumond.com [leedumond.com] on Topsy.com — August 25, 2009 4:35 PM
    7. The time to start thinking about exception handling is right after you click File > New Project. Exception handling shouldn't be something you "tack-on" to an application after the fact. Here, I discuss a practical approach to incorporating

    Trackback link for this post:
    http://leedumond.com/trackback.ashx?id=58

    » Comments

    1. Jay Cincotta avatar

      Great article, Lee! I agree whoeheartedly with your advice to "only catch exceptions that you are prepared to handle."

      I have a couple additional thoughts regarding logging.

      Certainly, all unhandled exceptions should be logged. And, though not quite as obvious, it is also very important to log handled exceptions.

      If, for whatever reason, you have code that is catching and swallowing exceptions, you really should log those swallowed exceptions. Hopefully, your logging system will allow you to ascribe lower severity levels to these exceptions -- but the crucial thing is that you know they're happening.

      Otherwise, you might spend a lot of time scratching your head tracking down an obscure bug report without a clue that the root cause of the problem that was mistakenly swallowed.

      Of course, mistakenly swallowing exceptions is to be avoided, and that gets back to the key point of this article. We should all be as specific as possible in catching only those exceptions we can handle. Also, the normal flow of control should not encounter any exceptions. They should be, er, exceptions -- as in rare occurences.

      But when exceptions are encountered, whether they are handled or not, logging the details including the full stack trace is a best practice that might save a lot of time troubleshooting a problem report.

      Jay Cincotta — May 18, 2009 3:09 PM
    2. Lee Dumond avatar

      @Jay:

      Okay, I understand you're selling a logging product, so that might explain the eagerness to log everything. ;-)

      You mention that cases in which you are swallowing exceptions should be logged. But in true practice, swallowing is not handling. Exception swallowing is a bad practice, as it conceals the occurrence of an error and could allow serious flaws in your program to go unnoticed.

      Actually, I would submit that one of the few rare cases in which swallowing can be justified is when something like a logging operation itself fails, and you do not wish to expose the resulting exception to your users. But in this circumstance you are not swallowing an exception that affects the main operation of your program, but are only swallowing an exception thrown by the logger. ;-)

      Lee Dumond — May 18, 2009 3:46 PM
    3. Jay Cincotta avatar

      Yes, we have a cool logging product, but I've been a big fan of logging for a couple decades. Not logging everything, btw. Just logging the important stuff that makes a difference in product support.

      I agree that exception swallowing is generally a bad practice. But it's done a lot. And to those insist that it's appropriate in their particular scenario, I say at least log it.

      Jay Cincotta — May 18, 2009 4:17 PM
    4. Nikki avatar

      Such a great point -- I wish my team leader agreed with you. Not only does he catch Exception, he then either returns false or throws a new exception with no inner exception, losing the stack trace! I've never had a harder time debugging.

      Nikki — May 19, 2009 12:29 PM
    5. Conker avatar

      I disagree, most of the times you dont know what kind of exceptions your code can throw.

      There nothing wrong with catching all exceptions and then either handle them or just log, ESPECIALLY in production enviropment.

      Conker — May 28, 2009 3:11 PM
    6. Lee Dumond avatar

      @Conker:

      >> most of the times you dont know what kind of exceptions your code can throw

      Yes, that is EXACTLY my point. If you have no idea what specific type of exception you're catching, how can you possibly hope to write code to properly handle it?

      Also, catching every possible exception ONLY for the purpose of logging them is a total waste of time. If you are actually *handling* the exception, and want to log it in the catch block, that's fine. (However, as I pointed out, it's not all that useful to routinely log *handled* exceptions.)

      Otherwise, if you have no legitimate strategy for properly handling the exception, you should let it remain unhandled, then centrally log all unhandled exceptions in your application-level (global) exception handler.

      Lee Dumond — May 28, 2009 3:43 PM
    7. Tushar avatar

      Good article, thanks for sharing.

      Tushar — May 30, 2009 4:21 AM

    » Leave a Comment