Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing an exception more than once loses its original stack trace

Tags:

c#

I have been playing around with Exceptions to learn more about how I should use them properly. So far, I know that throw keeps the original stack trace; throw new CustomException(...) is generally used when wanting to add more information about the exception that took place or add/change the message, or even change the type of Exception itself; and throw ex should never ever be used, unless I want to lose the original stack trace.

So I wrote a small program where I could catch and rethrow an exception several times while adding something to the original message.

public class Sample
{
    static void Main(string[] args)
    {
        new Tester().FirstCall();
    }
}

public class Tester
{
    public void FirstCall()
    {
        try
        {
            SecondCall();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace);
            Console.WriteLine(e.Message);
        }
    }

    public void SecondCall()
    {
        try
        {
            ThirdCall();
        }
        catch (GoodException ex)
        {
            throw new Exception(ex.Message, ex);
        }
    }

    public void ThirdCall()
    {
        try
        {
            FourthCall();
        }
        catch (ArithmeticException ae)
        {
            throw new GoodException("Arithmetic mistake: " + ae.Message, ae);
        }
    }

    public void FourthCall()
    {
        int d = 0;
        int x = 10 / d;
    }
}

Where GoodException is a custom exception implemented correctly.

I'm expecting the console to display something like this:

   at PlayingWithExceptions.Tester.FourthCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 67
   at PlayingWithExceptions.Tester.ThirdCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 59
   at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
   at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.

But instead I'm getting this:

   at PlayingWithExceptions.Tester.SecondCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 41
   at PlayingWithExceptions.Tester.FirstCall() in d:\Projects\PlayingWithExceptions\PlayingWithExceptions\Trying.cs:line 25
Arithmetic mistake: Attempted to divide by zero.

For some reason it only goes as far as the second call. Even though I'm passing the caught exception as an InnerException, the stack trace is still lost. I'm aware that if I just wrote throw instead of throwing a new exception, I could keep the original stack trace, but if I do that I won't be able to change the original message (which was the whole point of this exercise).

So my question is, what can I do to change the Exception message AND keep the original stack trace the whole way?

EDIT: Since an exception should not be used logic control and only caught once, the proper way to keep the original stack trace AND show the new message is to wrap the FourthCall in a try/catch (where the new Exception with its message is generated), and catch it only once all the way up in the FirstCall.

like image 981
Ana Ameer Avatar asked May 28 '14 23:05

Ana Ameer


People also ask

Is it good practice to Rethrow exception?

No of course not. There are cases when comment is still needed because the programming languages are not always best suited to describe what is going on very well.

What does end of stack trace from previous location where exception was thrown mean?

When the exception is restored, the following string is inserted in the stack trace to indicate the restore point: "End of stack trace from the previous location where the exception was thrown". This is similar to the way inner exceptions or marshaled exceptions are indicated in stack traces.

What is the point of throwing exceptions?

Exceptions are your way of letting your consumers know that something went wrong that you can't properly recover from. You're giving them the chance to either correct the issue, log the error, or pass the Exception up the chain until something useful can be done with it.


1 Answers

The stack trace isn't "lost" it's pushed into the InnerException, just like you told it to be. The "outer" exception in this case, did not participate in the call chain of the Inner exception - it's a brand new exception which originates in SecondCall, so that's the beginning of its stack trace.

And yes, the commenters are correct. To control your messaging, you won't do that by trying to set the message in the Exception object - Exceptions should be handled by code, messages are for users. So, you'll log the message, display it to the user, something like that.

like image 186
Jasmine Avatar answered Nov 15 '22 04:11

Jasmine