‘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 (10)

  1. Jason Coyne says:

    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.

  2. mihailik says:

    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.

  3. C. Watford says:

    How about handling TargetInvocationException’s? Is there a clean way to pass the InnerException on up by stripping the outer exception?

  4. C:

    This may do it:

    catch(TargetInvocationException e)

    {

      if (e.InnerException == null) throw;

      else throw e.InnerException;

    }

  5. Sam says:

    Does it make sense for the compiler to report a warning if it detects this anti-pattern? Maybe fxcop should/does detect this?

    I can not think of any real use for stripping the call stack (maybe security but it can be done in other ways). This is a really common mistake.

  6. C. Watford says:

    I currently do:

    catch(TargetInvocationException ee)

    {

      while( (ee.InnerException != null)

         && (ee.InnerException is TargetInvocationException) )

      {

         ee = ee.InnerException;

      }

      throw ee;

    }

    But I lose the stack trace don’t I…and thats what I don’t want to lose. I’ve also considered changing my highest level handler to strip off all of the targetinvocations and deal with just the innerexception, but still I find this to be awkward at best.

  7. 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

  8. 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.

  9. sam says:

    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

  10. I just noticed that my blog had birthday #3 (Sep 30th) . In tradition, some various stats… 384 posts.

Skip to main content