Throw vs Throw ex - The Why

01.17.07

I was talking to a friend of mine and he found my example of throw vs. throw ex interesting but he asked me a question that I didn’t expect, he asked me, "why?" I simply replied, "I don’t know, just don’t do it." But his insightful question made me curious. The answer to the question is in the real .Net language, the IL. When you compile your C# or VB.Net code just plain Throw becomes ReThrow but if you write Throw ex it becomes throw. In the IL snipit below Look at line 13 for JustThrowIT and line 14 in ThrowEX.

.method private instance void JustThrowIT() cil managed
{
      .maxstack 2
      .locals init (
            [mscorlib]System.Exception exception1)
       L_0000: nop
       L_0001: nop
       L_0002: ldarg.0
       L_0003: callvirt instance void throwDemo.Form1::ThrowsExceptions()
       L_0008: nop
       L_0009: leave.s L_001c
       L_000b: dup
       L_000c: call void [Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError([mscorlib]System.Exception)
       L_0011: stloc.0
       L_0012: nop
       L_0013: rethrow
       L_0015: call void [Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
       L_001a: leave.s L_001c
       L_001c: nop
       L_001d: nop
       L_001e: ret
       .try L_0002 to L_000b catch [mscorlib]System.Exception handler L_000b to L_001c
}
.method private instance void ThrowEX() cil managed
{
      .maxstack 2
      .locals init (
            [mscorlib]System.Exception exception1)
       L_0000: nop
       L_0001: nop
       L_0002: ldarg.0
       L_0003: callvirt instance void throwDemo.Form1::ThrowsExceptions()
       L_0008: nop
       L_0009: leave.s L_001c
       L_000b: dup
       L_000c: call void [Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError([mscorlib]System.Exception)
       L_0011: stloc.0
       L_0012: nop
       L_0013: ldloc.0
       L_0014: throw
       L_0015: call void [Microsoft.VisualBasic]
Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
       L_001a: leave.s L_001c
       L_001c: nop
       L_001d: nop
       L_001e: ret
       .try L_0002 to L_000b catch [mscorlib]System.Exception handler L_000b to L_001c
}
The ReThrow will pass on exception details were the throw is starting from scratch.