Geeks With Blogs

News Hi, my name is Vincent Grondin and I'm a senior consultant at Fujitsu, a consulting firm in Montreal, Québec. I'm starting that blog to share some of my thoughts and knowledge on .NET architectures and code. Being a consultant in the .NET world I come across many different things. Some good, some bad and others that are worth a blog post here whether they be good, or hmmm... shall I say, less good :) I hope you enjoy yourself while learning new stuff. Feel free to leave a comment or contact me anytime.
Vincent Grondin

One of the most common question people ask me in the teams I’m in is the following: Where should I put Try – Catch blocks? The second most popular is equally challenging: What is the best method to re-throw an exception? This post will try to answer both questions. Before I start with this topic, I must warn you that the following is not the official “best practices” but rather my own personal opinion on the subject, based on my past experience.  I think that Try – Catch blocks are a great asset of our programming language but they also tend to be the Achilles’ heel of our programs.  I say this because it’s not a good idea to write software that you'll have difficulties debugging effectively. It's often the case when people publish stack trace informations with eroneous line numbers in them.  What good is a stack trace when you end up on a "throw" instruction when trying to reproduce the bug in your developement environement?  That means make sure your exception’s “stack traces” have the right line numbers when you publish them because you only have one "try" at finding the cause of an error with stack traces...  This article assumes you’ve deployed your PDBs and that you are in a secured environment, but PDB issues are for another post... Let's get dive into this!

   

I will start this post by answering the second question mentioned above.  After catching an exception in your program, you decide to re-throw the exception back up the call stack.  You can do that with one of the following techniques:

A)     The “Throw” keyword alone.

B)      The “Throw” keyword followed by the variable name used to catch it (typically “ex”).

C)      Throwing a new exception (typed if possible) and adding the catched exception as the inner exception of the exception you’re about to throw.

So, which one of these techniques should we use to re-throw an exception?  Should we use any of those techniques?  Are they all the same and do they all yield the same results in the end?  Well, let’s give it a try J

Here’s a solution that you can download and try every combination yourselves.  In the mean time, here are the results:

 

Using technique B is the worst practice of all 3.  It will inevitably break your stack trace and replace your original exception’s line number with the line number at which the exception was re-thrown.  This renders your stack trace almost useless.  Good luck in your debug sessions...  See the following stack trace screenshot which should show an error at line 119 but we’re seeing line number 109 instead.

 

Using the A technique can be as damageable as the B technique even though we see this technique of simply using the “throw” keyword almost everywhere...   Look at this stack trace which displays line number 175 when in reality it should be displaying line number 168.  How shocking!

 

The only technique that allows re-throwing an exception and that keeps the stack trace’s line numbers intact is C.  Look at this stack trace and you'll see the correct line number is shown which is 257.  But throwing a new exception has a cost on performance.  In fact, I do not consider this to be a decisive factor but, yes, creating another exception is time consuming.  Then again, it’s time consuming on and “exceptional” basis...  So once in a while, your program will be slower to tell you to contact your administrator because something went wrong...  So what?  Remember that your program should do something other than generate exceptions all the time and if it’s not, then you’re already in trouble.  I’m sure your client isn’t paying you to build an exception generator.

Of course the default “bubble up” is always the best option but sometimes, you have to catch possible exceptions.  This exception was bubbled up and gives us the right line number being 206.  My advice to you is this: be very precise in which exception you need to catch when this situation arises.  No need to catch more than you should, let other unplanned exception bubble up and re-throw the exception you wanted to catch as the inner exception in a new exception.  Hopefully these screen shots were enough to have you download the solution above and try these different try – catch combos.

Now that you know a little bit more about the side effects of re-throwing an exception using something else than throwing a new exception, let’s see where we should use try – catch blocks.  Ever heard of “stack starters”?  Of course you didn’t since this is my very own term for “event handlers”, what was I thinking.  Event handlers are THE most important thing to secure when speaking of error handling.  In my book, each and every “event handler” has to be protected by a “try – catch – all” exception block.  That means a try – catch block catching “Exception” as its type.  Of course you can always rely on good ol’ global handlers to publish all your exceptions.  Please do so!!!  But use global handlers as safety nets...  Why?  Because YOU are responsible for securing your code from unhandled exceptions.  Remember that when writing code inside an event in your program, you’re simply coding inside an area where another programmer momentarily passed you control over the execution of HIS code.  Welcome to the bottom of the programming food chain, where I unfortunately reside too...  Here’s an example of what can happen if you don’t systematically catch all exception in the events you consume.  Click here for a screen shot of the code I want to show you or fire up your favourite disassembler program (mine being Reflector) and browse to the System.Windows.Forms namespace to find the DataGrid.  Open the DataGrid and disassemble the OnPaint method.  In there you will be able to see that the programmer who wrote this piece of code has guarded against anything that could happen in his code....  Good thing!  Every programmer should keep his shelves tidy and clean up the mess in his state variables when something goes wrong in his code.  Let’s dig a little deeper.  Locate this line in the code:   base.OnPaint(pe);.   Disassemble it too...  There you will see the base class of the DataGrid actually calls the event handler you added when you consumed the OnPaint event in your code.  But what happens to the gentlemen’s code if YOU forgot to catch all exceptions in your code when you consumed the OnPaint event?  Yep, he’s going to catch it for you....  Great you think?  Not really...  You made him think HIS code threw the exception and look at all the code he’s going to run to clean up what he thinks is his mess...  You're lucky, there wasn't a MessageBox.Show() in there displaying a debug message in cantonese!  Ok you need to set aside the fact that in this case, he’s detecting whether or not he should simply re-throw the exception or do his stuff with this line of code so, I’m busted ...  It’s hard to find a real code example that matches what I want to demonstrate.  You need to keep in mind though that when using controls this scenario could always happen.  Hopefully this example convinced you to secure your “stack starters” with a “try – catch – all” block.

Sometimes catching exceptions in your business layer or your data layer is inevitable but, you should always consider re-throwing the exception to signal the initial caller that something went wrong at one point in the chain.  When I need to stop the execution of an action in my program, I always choose exceptions over Boolean returns for my methods.  To me, exceptions are far easier to handle than having to take care of returning a Boolean in each method I call and having to deal with coding the return chain for every method.  Most of the time, when an exception happens in my business layer, its serious enough for me to break whatever I was doing and signal the error back up.   Rarely have I seen “something unexpected happening” in my business or data layer which would not influence the outcome of the initial call.

Another thing worth mentioning is be aware of not hiding exceptions.  Using the following pattern is something you should try to use only if necessary as it renders debugging a real nightmare.
In french I call this pattern “Try – Cache” which could translate to "Try-Hide" and means try to hide the exception...  Anyone remembers the good ol’ days of “On Error Resume Next” in VB?  What a smart way to bullet proof your application against that pesky message from Windows (huh... NO... it’s not).

I hope you see things differently or at least from another eye now and that this blog post was interesting even though it was long.  Happy code reviewing!

Posted on Monday, October 19, 2009 5:02 PM | Back to top


Comments on this post: My thoughts on Try – Catch – Throw

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Vincent Grondin | Powered by: GeeksWithBlogs.net