Geeks With Blogs

News



Microsoft Store

Support This Site


AddThis Social Bookmark Button

Locations of visitors to this page

Subscribers to this feed

TwitterCounter for @sdorman

Creative Commons License


Scott Dorman Microsoft MVP, Software Architect, Developer, Author

Exception handling seems to be a common problem for .NET developers, particularly younger developers. We pretty much all know that you should wrap operations that have the potential for failing in a try/catch block if you are interested in being able to do something about the error that occurred. I'm not going to talk about the rules and guidelines for using exception handling. Instead I'm going to focus on a particular aspect of exception handling, which I tend to call exception bubbling.

Exception bubbling means that even though you are catching the exception and doing something with it, you want that exception to "bubble" up from your code to the calling code so it has a chance to do something with that exception. This is a fairly common scenario, but it has the potential to cause some major problems when you are debugging.

I'm sure most of the exception bubbling code you've seen looks similar to this

   1: try
   2: {
   3:     // do some operation that can fail
   4: }
   5: catch (Exception ex)
   6: {
   7:     // do some local cleanup
   8:     throw ex;
   9: }

This code looks perfectly reasonable and does the job. It properly catches the exception, does some local cleanup and then bubbles the exception up the chain. (A side note here is that you really shouldn't catch a general exception like this. I'm doing this for simplicity in the examples, but you should be catching specific exceptions and only those that you can do something about.)

However, how  many of you have seen code that looks like this

   1: try
   2: {
   3:     // do some operation that can fail
   4: }
   5: catch (Exception ex)
   6: {
   7:     // do some local cleanup
   8:     throw;
   9: }

There is a subtle difference between these two calls that won't be apparent until you are trying to debug the problem. That difference is in the stack trace information that gets sent with the exception.

In the first case, the stack trace is truncated below the method that failed. What this means is that when you look at the stack trace, it will look as if the exception originated in your code. This isn't always the case, particularly if you are bubbling up a CLR generated exception (like a SqlException). This is a problem known as "breaking the stack", because you no longer have the full stack trace information. This happens because you are in essence creating a new exception to throw. 

By using "throw" by itself, you preserve the stack trace information. You can confirm this by looking at the IL generated for these two code blocks. This makes the difference very obvious since in the first example the IL instruction called is "throw" while in the second the instruction is called "rethrow".

Before you run and change all of your code, there are still places where "throw ex" is appropriate. There are times when you want to add information to the exception that was caught or change it into a more meaningful exception. In these instances you actually want a new exception to be thrown. Again, there are two ways you can do this. The most common way that I have seen is

   1: try
   2: {
   3:     // do some operation that can fail
   4: }
   5: catch (Exception ex)
   6: {
   7:     // do some local cleanup
   8:     throw new ApplicationException("operation failed!");
   9: }

However, this still suffers the problem of breaking the stack. Here you are generating a completely new exception and loosing any of the stack trace information from the original exception. What you really want to do is

   1: try
   2: {
   3:     // do some operation that can fail
   4: }
   5: catch (Exception ex)
   6: {
   7:     // do some local cleanup
   8:     throw new ApplicationException("operation failed!", ex);
   9: }

By passing the original exception to the ApplicationException you are preserving the original exception, and it's stack trace information, as the inner exception to your ApplicationException.

To wrap everything up

    1. Only catch exceptions if they are important to you and you need to do some sort of cleanup as a result.
    2. If you need to bubble an exception up the chain, use "throw" by itself.
    3. If you need to add information to the exception or repackage it, always pass the original exception as the inner exception.
Posted on Monday, August 20, 2007 11:26 AM .NET (General) , .NET (C#) | Back to top


Comments on this post: Difference between "throw" and "throw ex" in .NET

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Nice post. Thanks for clearing this up!
Left by David on Aug 21, 2007 11:20 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
This article is really useful. This piece of information has never crossed my mind. Thanks for this wonderful article.
Left by Bhabani on Sep 21, 2007 2:54 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Thanks, Nicely explained.
Left by Vikas Goyal on Dec 29, 2007 6:29 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Hi,

Great article! I had a question for you: You say that one should let the exception bubble up, unless it can be handled. But wouldn't it be better to always catch the error and display a user-friendly message to the user, and log the error? A run-time exception will just frighten and confuse the user.

Or do you recommend letting the exception bubble up, and creating a generic error page, which is displayed for all errors, and does logging, etc.?

Thanks and regards,
Donniel
Left by Donniel Thomas on Jan 17, 2008 2:43 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
@Donniel, The problem with catching the error and displaying it to the user is that the user may not actually need to know about the error and/or be able to do anything about it. If you just catch and log the error then you can be potentially hiding the problem and cause other problems in the long run.

If you've done a good job of defensive programming the most common exceptions will be handled somewhere in your call chain. Creating a generic error page for any unhandled exceptions isn't a bad idea as long as you don't use it as a "catch all" for any exception.
Left by Scott on Jan 17, 2008 11:37 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Good article !! Clearly explained the difference.
Left by Sebina Mariadhas on Feb 20, 2008 1:56 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Wonderful article.Really nice.Thanks for the clarification
Left by TATA on Apr 28, 2008 7:01 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Nice article. Explanation is superb with sweet and simple code snippets.

Nishanth
www.dotnetrocks.wordpress.com
Left by Nishanth Nair on May 08, 2008 4:54 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
@Sebina, @TATA, @Nishanth: Thanks!
Left by Scott on May 25, 2008 3:17 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
I have a question for you scott. What if we throw a new exception and add the ex.stacktrace along with the ex.message?
Left by Mathew on Aug 01, 2008 3:14 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Mathew, the best option for throwing a new exception is to include the original one as a nested exception. This is actually cleaner than adding the stack trace data to the message of the new exception as it keeps the message cleaner and keeps the information where debuggers and support people are most likely to expect it.
Left by Scott on Aug 02, 2008 5:18 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Very simple to understand but excellent at the same time !!
Left by Hassan Khan on Sep 19, 2008 6:38 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Wonderful! informative and crisp.
Left by Virendra Singh on Feb 25, 2009 10:33 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Nice Article
Left by Harjit on Jul 20, 2009 5:49 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Nice article, liked it, thanks for the info

www.sporteilat.co.il
Left by joku on Sep 29, 2009 9:13 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Great article! I've been doing a lot more client-side scripting of late, and have gotten a bit rusty on .NET. This did a great job of refreshing the memory on .NET exception handling. I bet it's nice to know that an article you wrote in 8/07 is still helping people 2-1/2 years later.
Left by David Holt on Dec 03, 2009 2:40 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Thanks for sharing the the knowledge
Left by Mridul on Dec 04, 2009 1:09 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
This article is real crisp and easy to grasp. Hit the nail on its head, covering the very subtle points in throw, where there is always a lot of ambiguity. Thanks.
Left by Srinivasan M on Dec 18, 2009 1:13 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Very informative indeed!!!!

Thanks for presenting it in a very lucid style.

Cheers.
Left by Syed Nadeem on Mar 08, 2010 4:09 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Good Article...

I found my solution here...

Thanks,
Shalem
Left by Shalem on Mar 09, 2010 12:29 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Page is not displayed properly... i am unable to see the left side contents of the page
Left by Balamurugan on Jun 30, 2010 6:14 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Exactly what I wanted to know. Thanks.
Left by RK on Jul 21, 2010 12:54 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Thank you for your explanation!
Left by HK on Jul 22, 2010 10:57 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Gr8 article... Thanks! :-)
Left by sam on Sep 06, 2010 5:25 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Really a nice explanation... useful to everyone who wants to know the difference..
Left by Hari Shankar on Jul 12, 2011 3:11 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Thank you for the information. I really appreciate this.
Left by Prakash on Sep 14, 2011 3:34 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
really a nice explanation....it is very use full informatin
Left by sss on Jan 06, 2012 6:03 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
very nice description and explanation of throw
Left by Uma on Jan 18, 2012 12:41 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Really helpful.
Thanks.::)
Left by Manish on Jul 09, 2012 2:36 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
What a nice and clean difference posted here.
Left by Bharat Bhushan on Jun 24, 2013 11:31 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Great ! Thanks a lot
Left by ShoushouLeb on Apr 29, 2014 9:19 AM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Awesome info....

Thanks much!
Left by Dhana on Jun 05, 2014 6:04 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Thank you very much for this article!
Left by Sergey on Jul 09, 2014 12:20 PM

# re: Difference between "throw" and "throw ex" in .NET
Requesting Gravatar...
Actually, it isn't quite correct that you "preserve" the stack trace when you use "throw". To see this, try the following:

void foo()
{
try { bar(); }
catch (Exception ex) { Debug.WriteLine("\r\nfoo: " + ex.ToString()); }
}

void bar()
{
try { throw new ApplicationException("Ooops"); }
catch (Exception ex)
{
Debug.WriteLine("\r\nbar: " + ex.ToString());
throw;
}
}

The exception printed by bar() does NOT have an identical stack trace to that printed in foo(). The former will refer to the line where the exception was thrown, but the second will refer to the line where the exception was RE-thrown.

This can be an issue in some cases. Often it will be clear from the other stack frames where in the try-block you were (because the try block called into something that called into something, and we can infer from this where we were). But in some cases, the most typical being NullReferenceExceptions, there may be many places in the try-block where it might have failed and impossible to say from the stack trace of the re-thrown exception where it happened.

The only way to fully preserve the stack trace is to throw a brand *new* exception with inner exception set. Change the catch block in bar() to

throw new ApplicationException("Aiai", ex);

and notice the difference. Here, the exception (chain) caught in foo retains the complete trace.

However, throwing new exceptions presents another set of challenges if you thought you'd base exception handling on the exception type thrown (which is of course what's we're "supposed" to do, and the reason why catch blocks work the way they do - with multiple catches handling most-to-least specific exception types).

Usually, good code should contain a lot of throw statements and very few try-catches. In many cases, a single, centralized handler for logging purposes is a good starting point. Centralization may be used in many other contexts as well - for instance, you could have a base class for data access that can handle a deadlock by logging the error and retrying (deadlocks are basically unavoidable, but usually extremely hard to reproduce - so simply trying again is often a good solution!) before giving up and throwing anything to the user.
Left by Øystein on Sep 16, 2014 4:08 AM

Your comment:
 (will show your gravatar)
 


Copyright © Scott Dorman | Powered by: GeeksWithBlogs.net | Join free