Random header image... Refresh for more!

Just throw;ing this out there.

In C#, what’s the difference between “throw;” and “throw e;”?

This is one of those “Interview Question” tidbits of language trivia.  It’s the sort of thing that you can probably remember the exact circumstances where you learned about it, because it was probably preceded by three hours of frustration and confusion.  It’s the sort of thing that I’d always assumed separated the serious C# programmers from the casual passerby.

Until today…

Today, this issue came up and I was honestly surprised by the number of people around me who didn’t know the difference, and even more surprised about how the difference seems to be missing from official sources, like the C# Language Specification1, so I felt compelled to write about it.

To clarify, I’m asking about the difference between “throw;” and “throw e;”, where you’re rethrowing an exception that was caught inside a catch statement.

In other words, this:

public static void DoSomething()
{
    throw new Exception("Thrown on line 12.");
}

public static void ExceptionRethrower()
{
    try
    {
        DoSomething();
    }
    catch (Exception e)
    {
        LogException(e);
        throw e;
    }
}

So, DoSomething(); does something and throws an exception2.  You want to catch it and log it or whatever, but you want the exception to bubble up to the callers of ExceptionRethrower() for some reason.  I’m sure you’ve written code like this somewhere.

And there it is, “throw e;” at the end of the catch.  Let’s write a bit of code to call this function and catch the exception, and see what turns up.

static void Main(string[] args)
{
    try
    {
        ExceptionRethrower();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

Okay…  So, the function DoSomething is throwing an exception, which is caught and logged in ExceptionRethrower, then rethrown up to Main, where the exception and its stack trace are printed out.  That means the stack trace will have DoSomething on top, then ExceptionRethrower, followed by Main on the bottom, right?

System.Exception: Thrown on line 12.
   at ThrowExample.Program.ExceptionRethrower() in E:\svn\Projects\ThrowExample\ThrowExample\Program.cs:line 26
   at ThrowExample.Program.Main(String[] args) in E:\svn\Projects\ThrowExample\ThrowExample\Program.cs:line 34

Nope.

It’s got Main and ExceptionRethrower, but what happened to DoSomething?  And the exception message says that I threw it on line 12, but according to the stack trace, I was nowhere near line 12.

So…  WTF?

Let’s play with the debugger, instead.  I’m going to comment out the try/catch in Main and let the exception fall out and kill my app and see what VS has to say about it.

Line 26 is my “throw e;”.  It’s eating my stack trace!

Okay, so, let’s see what happens if I just “throw;”, instead.

System.Exception: Thrown on line 12.
   at ThrowExample.Program.DoSomething() in E:\svn\Projects\ThrowExample\ThrowExample\Program.cs:line 12
   at ThrowExample.Program.ExceptionRethrower() in E:\svn\Projects\ThrowExample\ThrowExample\Program.cs:line 26
   at ThrowExample.Program.Main(String[] args) in E:\svn\Projects\ThrowExample\ThrowExample\Program.cs:line 34

Hey, look!  DoSomething() is there in the trace now, with the exception originating on line 12 like it should.

So, there’s your answer to the original question:  Rethrowing the instance, as in “throw e;” will discard the existing stack trace and make it look like the exception originated on the “throw e;” line, while a parameterless “throw;” will retain the original stack trace.

Sort of…

Look at that second stack trace again.  Look closely at the line numbers.  It still has line 26, where the “throw;” is located, but the call to DoSomething() is on line 21.  It should, like the call stack below shows, have DoSomething() line 12 (Where the exception was thrown), then ExceptionRethrower() line 21 (Where DoSomething() was called), then Main() line 34 (Where ExceptionRethrower() was called).

How did line 21 get tossed aside for line 26?  Well, think about the stack for a moment.  When you’re generating a stack trace, either on the call stack side or on the exception side, each function has a single frame, pointing at the last line that was executed.  When you’re at line 12 in DoSomething(), the last line in ExceptionRethrower() was line 21.  However, once the exception is thrown, you hit the catch in ExeceptionRethrower() and get rerouted, so by the time you end up in Main(), the last line called in ExceptionRethrower() was line 26 at the throw;.  This also means that if you throw, catch, and rethrow, all in a single function, the stack trace will end up pointing at the rethrow, regardless of whether you’re using “throw;” or “throw e;”.

Of course, if that whole “call stack” explanation I just gave actually held any water, then adding in a finally block would cause the stack trace to point at the last line of the finally, because that was the last line of the function executed.  However, that’s not the case.  Even when you add in the finally, the stack trace still points at the throw line.   But hey, the explanation still sounds plausible, so I’m leaving it in this post.  I’m sure it’s something close to that, anyway.  It’s a good thing finallys don’t affect the trace, because if it did, I can’t imagine how wildly FUBARed some stack traces would end up. 3

In general, if you have to catch and rethrow an exception, you should use the plain throw;.  If you rethrow the instance using throw e;, you’ll have a hard time debugging and testing, because your stack traces will all dead end at a throw that’s nowhere near the source of the problem.  However, if you’re writing a library or service for third-party consumption, then throw e; provides a quick way to let exceptions get out to the callers while hiding some of the implementation details of your code by killing off the call stack. 4

Another thing to be aware of is that whichever rethrowing scheme you use, the original instance is used.  That means that if you save off the exception instance for later, the stack trace will have been wiped out or modified by the time you want to use it.  Even more subtle and insidious is that this means that if you’re using a threaded logger of some sort, there’s a chance that the stack trace will be mangled by the time the logger gets around to writing out the exception.  In other words, some times the log will say the exception’s on line 12, other times it’ll say the exception’s on line 26. 5

The sample code is here: http://www.mathpirate.net/svn/Projects/ThrowExample/

To reiterate, for those who skipped to the end:

  • “throw e;” wipes out the stack trace, restarting it at the point of the throw.
  • “throw;” maintains the existing stack trace, but still mangles the stack of the current frame.
  1. I couldn’t find it in there, anyway… []
  2. From line 12, obviously… []
  3. By the way, speaking of finally blocks, did you know that you can’t return from one?  There’s another bit of obscure language trivia for you. []
  4. Of course, if you actually think that’s a good idea, then you probably will want to rethink your exception handling strategy in general…  That’s just the only reason I could think of for deliberately using throw e; to rethrow a caught exception. []
  5. Have fun debugging that one… []

December 13, 2010   No Comments

Straight to the Source

http://mathpirate.net/svn/Android/AndroidExperiment/

And here’s the project in SVN.  I think.  Enjoy.

December 12, 2010   No Comments

Let’s Start a Dialog

.Net:

if(MessageBox.Show("Are You Sure?", MessageBoxButtons.YesNo) == DialogResult.Yes) { DoWork(); }

Android:

     AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
     dialogBuilder.setTitle("Save File");
     dialogBuilder.setMessage("Are you sure?");
     dialogBuilder.setPositiveButton("Yes",
       new DialogInterface.OnClickListener()
       {
        public void onClick(DialogInterface dialog, int which)
        {
         doWork();
        }
       });
     dialogBuilder.setNegativeButton("No",
       new DialogInterface.OnClickListener()
       {
        public void onClick(DialogInterface dialog, int which)
        {
         dontDoWork();
        }
       });
     dialogBuilder.setCancelable(true);
     dialogBuilder.setOnCancelListener(
       new DialogInterface.OnCancelListener() {
     
     public void onCancel(DialogInterface dialog)
     {
      dontDoWorkHereEither();
     }
    });
     dialogBuilder.show();

OMG.  WTF.  SERIOUSLY?

Why write just one line of code when TWENTY-NINE will do the same thing just as well?

December 12, 2010   No Comments

Android Launch

December 12, 2010   No Comments

Ew…. I feel dirty now.

I just realized what this reminds me of.  Some of this Android stuff feels like MFC.  That’s why it’s tripping my icky sensors.  I have to register event messages in one file, then I have to make a big and ugly switch statement in another file that dispatches my actions using magic constants.

December 11, 2010   No Comments

The Holy Grail

I just found a Twitter API wrapper that also handles Yammer.  Oh the joy!  It’s exactly everything I’ve ever wanted and more!

September 5, 2010   No Comments

Source Code Repository

By the way, for those of you playing the home game, I’m checking in the code as I go:  http://www.mathpirate.net/svn/Projects/EchoChamber/

September 4, 2010   No Comments

Um. No.

for (int i = 0; i < PrefixLength; PrefixLength++)
{
     prefixQueue.Enqueue(EchoToken.TerminatorWord);
}

Oops.

September 3, 2010   No Comments

Maybe they need to read their own best practices.

I got this error today.  It is a magnificent demonstration of several layers of FAIL.

August 19, 2010   No Comments

Windows Workflow Quick Tip

Given that I spent all day looking for this and had trouble finding it (Okay, I’ll be honest, I skipped a page in the book because it didn’t look relevant, but whatever), if you ever need to get the name of the currently executing state on a Windows Workflow (WF) State Machine Workflow, there’s a class you can use called StateMachineWorkflowInstance.  StateMachineWorkflowInstance has a property called CurrentStateName to give you the name as a string and another called CurrentState, which gives you an instance of the StateActivity object that’s currently running.

For some reason unknown to me, StateMachineWorkflowInstance isn’t derived from WorkflowInstance1, so the WorkflowInstance you get back from WorkflowRuntime.CreateWorkflow can’t be cast to a StateMachineWorkflowInstance instance.  Instead, you have to new up the object yourself.  The constructor takes the WorkflowRuntime where the workflow is executing, and the Guid returned by the InstanceId property on the WorkflowInstance that was returned by CreateWorkflow for the workflow you want to know the state for.

  1. Cause, you know, .Net is all object orienty and such, so that’s what I would’ve done… []

June 15, 2010   No Comments