Search code examples
c#exceptionthrowrethrow

Throw VS rethrow : same result?


refering to a lot of documentation on the net, particularly on SO, eg : What is the proper way to re-throw an exception in C#? there should be a difference between "throw e;" and "throw;".

But, from : http://bartdesmet.net/blogs/bart/archive/2006/03/12/3815.aspx,

this code :

using System;

class Ex
{
   public static void Main()
  {
  //
  // First test rethrowing the caught exception variable.
  //
  Console.WriteLine("First test");
  try
  {
     ThrowWithVariable();
  }
  catch (Exception ex)
  {
     Console.WriteLine(ex.StackTrace);
  }

  //
  // Second test performing a blind rethrow.
  //
  Console.WriteLine("Second test");
  try
  {
     ThrowWithoutVariable();
  }
  catch (Exception ex)
  {
     Console.WriteLine(ex.StackTrace);
  }
}

 private static void BadGuy()
 {
   //
   // Some nasty behavior.
  //
   throw new Exception();
 }

   private static void ThrowWithVariable()
 {
   try
   {
         BadGuy();
   }
  catch (Exception ex)
  {
     throw ex;
  }
}

   private static void ThrowWithoutVariable()
{
  try
  {
     BadGuy();
  }
  catch
  {
     throw;
  }
   }
}

gives the following result :

$ /cygdrive/c/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe Test.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.

$ ./Test.exe
First test
   at Ex.ThrowWithVariable()
   at Ex.Main()
Second test
   at Ex.ThrowWithoutVariable()
   at Ex.Main()

which is in complete contradiction with the blog post.

The same kind of result is obtained with the code from : http://crazorsharp.blogspot.com/2009/08/rethrowing-exception-without-resetting.html

Original question : what am I doing wrong ?

UPDATE : same result with .Net 3.5 / csc.exe 3.5.30729.4926

SUMUP : all your answers were great, thanks again.

So the reason is effectively inlining due to the 64-bit JITter.

I had to choose only one answer, and here is why I have choosen LukeH answer :

  • he guessed the inlining problem and the fact it may be related to my 64-bit architecture,

  • he provided the NoInlining flag which is the simplest way to avoid this behavior.

However this issue now rises another question : is this behavior compliant with all the .Net specifications : the CLR ones and the C# programming language ones ?

UPDATE : this optimization seems compliant according to : Throw VS rethrow : same result? (thanks 0xA3)

Thanks in advance for your help.


Solution

  • I can't replicate the problem -- using .NET 3.5 (32-bit) gives me the same results described in Bart's article.

    My guess is that the .NET 4 compiler/jitter -- or maybe it's the 64-bit compiler/jitter if this is happening under 3.5 too -- is inlining the BadGuy method into the calling methods. Try adding the following MethodImpl attribute to BadGuy and see if that makes any difference:

    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
    private static void BadGuy()
    {
        //
        // Some nasty behavior.
        //
        throw new Exception();
    }