'throw e;' vs. 'throw;'

Someone asked what the practical differences are between 'throw;' (no arguments) and 'throw object;'   (in C# syntax).

Specifically, what's the difference between:

 
        catch (Exception e)
        {
            throw;
        }

and

         catch (Exception e)
        {
            throw e;
        }

This is mildly related to the 'catch' vs 'catch(Exception e)' vs. 'catch  (SomeSpecificException e)'. I'll avoid talking about catch, and just focus on the rethrow.

What's the same:

  1. Both throw an exception.

  2. Both have the same debuggability problems associated with catch / rethrow.

  3. They can be called in the same way.  I used code like:

             catch (Exception e)
            {            
                if (...) 
                    throw;
                else
                    throw e;
            }
    

    as an academic way to demonstrate that they must have some similar properties. Never actually write code like that!

  4. They can both be used in a naked catch block, although as difference #1 below mentions, 'throw e'; can't be used to rethrow the current exception.

         catch
        {
            throw new MyWrapperException();
        }

What's different:

  1. 'throw;' can only be used in the lexical scope of a catch block since it must gaurantee having a current exception. 'throw e' can be used anywhere.
  2. 'throw e' lets you provide a new exception object, such as a wrapper around the original exception.
  3. Only 'throw' can be used to rethrow the current exception within a naked catch block
  4. They both rethrow the current exception object, but “throw e;” resets parameters on it like the Exception.StackWalk property.
  5. They generate different IL opcodes. C#'s 'throw;' compiles to the 'rethrow' IL opcode, which doesn't take any parameters on the IL stack. 'throw e;' compiles to the 'throw' IL opcode, which takes 1 IL stack parameter: the exception to throw.
     

Check out the C# spec for more details

Comments

  • Anonymous
    February 15, 2007
    I use this as one of my interview questions. The most important difference in my mind is something you touched on, but did not make clear (IMO) In the throw e; syntax, the stack trace is reset to the current catch location, which could be significantly different from where the original exception was thrown. In the throw; syntax, the original stack trace is preserved, even if you have bubbled up several layers in the original call stack from where the exception is thrown.   this is of course just a text representation, not the actual location in the call stack, which has already been unwound (as your "problems" article correctly reports.

  • Anonymous
    February 15, 2007
    And please also add there common practice for wrapped rethrow: throw new MySpecialException("message",e); It is such a nightmare to debug code where exception's stack trace information is carefully cutted off. Please, do teach them to do it correct way, they listen to you.

  • Anonymous
    February 21, 2007
    The comment has been removed

  • Anonymous
    February 21, 2007
    C: This may do it: catch(TargetInvocationException e) {   if (e.InnerException == null) throw;   else throw e.InnerException; }

  • Anonymous
    February 21, 2007
    The comment has been removed

  • Anonymous
    February 22, 2007
    The comment has been removed

  • Anonymous
    February 22, 2007
    C - unfortunately, any form of catch-rethrow is going to lose the stack, per issues here: http://blogs.msdn.com/jmstall/archive/2007/02/07/catch-rethrow.aspx

  • Anonymous
    February 22, 2007
    Sam - I could imagine a good fxcop rule around this area, although it would require some good articulation skills to determine exactly what. However, I don't know if this usage pattern is common enough to make it a valuable rule.

  • Anonymous
    February 23, 2007
    Hi Mike Turns out there is an fxcop rule already - It's called: "Rethrow to preserve stack details" The issue is pretty common: http://www.google.com/codesearch?hl=en&q=+lang:c%23+%22throw+e%3B%22&start=20&sa=N

  • Anonymous
    October 07, 2007
    I just noticed that my blog had birthday #3 (Sep 30th) . In tradition, some various stats... 384 posts.