8 comments

  1. FxCop will inform you about this as well.

    robertka

  2. I've tried both 'throw' and 'throw e' they produce the same result .. means : The stack trace is reseted.

    I use it with Visual Studio 2005.

    So I'm lost ….

    Arif

  3. I think someting more is going on in this case. Are you sure there is a stacktrace to begin with? You could check this by setting a breakpoint in the catch and inspect the StackTrace property in the watch window before it is retrown. Are you doing anything special in the catch block regarding to the exception you are re-throwing?

    frankb

  4. Actually, throw; does slightly modify the stack trace: The top frame, to be exact. The code below demonstrates this.

    using System;

    public class C
    {
    public static void Main(string[] args) {
    try
    {
    Rethrow();
    }
    catch (Exception e)
    {
    Console.Out.WriteLine(“Rethrown exception is ” + e);
    // output original stack trace except the Rethrow() stack frame frame now indicates the line where the exception was rethrown rather than the line where the exception was thrown
    }
    Console.ReadKey();
    }

    static void Rethrow()
    {
    try
    {
    throw new Exception();
    }
    catch (Exception e)
    {
    Console.Out.WriteLine(“Original exception is ” + e); // outputs original stack trace
    throw;
    }
    }
    }

    The Nobb

  5. The Nobb is right, thanks for clearing that up! Rethrow does modify the stacktrace, but it is not as bad as it looks, you only loose one line of information and get a line for the rethow in return

    I modyfied your code a bit to make it more clear what happens when the Exeption comes from a deeper than the catch block, (also you had forgotten the actual throw; statement in the sap.

    This sample demonstrates that it is not naccaraly the top frame that gets modified, but the line of the catch is replaced by the line of the throw.

    using System;
    public class C
    {
    public static void Main(string[] args)
    {
    try
    {
    Rethrow();
    }
    catch (Exception e)
    {
    Console.Out.WriteLine(“Rethrown exception is ” + e);
    // output original stack trace except the Rethrow() stack frame frame now indicates the
    // line where the exception was rethrown rather than the line where the exception was thrown
    }
    Console.ReadKey();
    }

    static void Rethrow()
    {
    try
    {
    ThrowException();
    }
    catch (Exception e)
    {
    Console.Out.WriteLine(“Original exception is ” + e);
    throw;
    // outputs original stack trace throw;
    }
    }

    static void ThrowException()
    {
    throw new Exception();
    }
    }

    see the output here

    Original exception is System.Exception: Exception of type ‘System.Exception’ was thrown.
    at C.ThrowException() in C:\Program.cs:line 35
    at C.Rethrow() in C:\Program.cs:line 23

    Rethrown exception is System.Exception: Exception of type ‘System.Exception’ was thrown.
    at C.ThrowException() in C:\Program.cs:line 35
    at C.Rethrow() in C:\Program.cs:line 28
    at C.Main(String[] args) in C:\Program.cs:line 8

    frankb

  6. So, according to the Rethrow example, the original stack trace is lost even with “throw;”?

    If you use
    throw new Exception(“new message”, ex);

    instead of
    throw;

    then the original trace should be nested. But, this seems very annoying to me that the original exception can not be re-thrown without either losing the original stack trace or creating a new exception.

    Johnny

  7. So, according to the Rethrow example, the original stack trace is lost even with “throw;”?

    If you use
    throw new Exception(“new message”, ex);

    instead of
    throw;

    then the original trace should be nested. But, this seems very annoying to me that the original exception can not be re-thrown without either losing the original stack trace or creating a new exception.

    Johnny

  8. The Throw; will change one frame of the stacktrace, that is the frame of the method which contains the catch(Exception) {trow;}. This frame will now point to the line that contains the throw instead of the line that contains the call that actually caused the exception.
    The rest of the stacktrace, leading from the original cause to this catch will remain as it was.

    There is however another way to keep the stacktrace in tact (poking in the Exception object with relfection). I’ll see if I can do a post on that in the near future.

    frankb

Comments are closed.