Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rethrow an Exception with correct line numbers in the stack trace

Tags:

c#

.net

throw

You are apparently able to rethrow an Exception without discarding the stack trace in .NET.

However it doesn't appear to be working.

Basic usage I'm following is thus:

    [WebMethod]
    public void ExceptionTest()
    {
        try
        {
            throw new Exception("An Error Happened");
        }
        catch (Exception ex)
        {
            evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
            throw;
        }
    }

Problem is, the line number in the exception in the line of the throw; line, not the original throw new line.

I've tested it in a simple exe project and without the logging to the windows log line. It doesn't make any difference, the stack trace always has the wrong line number in it, making it less than useful.

Why is it doing this? How do I do it correctly?

like image 874
RoboJ1M Avatar asked Feb 06 '14 10:02

RoboJ1M


People also ask

How do you Rethrow an exception?

If a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.

How can I get line number in stack trace?

The java. lang. StackTraceElement. getLineNumber() method returns the line number of the source line containing the execution point represented by this stack trace element.

How do I Rethrow exceptions in VB net?

And always use just "Throw", not "Throw ex". Throw will rethrow the handles exception keeping it's stack intact.

What is Rethrow exception in C#?

When an exception is caught, we can perform some operations, like logging the error, and then re-throw the exception. Re-throwing an exception means calling the throw statement without an exception object, inside a catch block. It can only be used inside a catch block.


2 Answers

You do not lose original exception if you place it in an inner exception.

[WebMethod]
public void ExceptionTest()
{
    try
    {
        throw new Exception("An Error Happened");
    }
    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        throw new Exception("Your message", ex);
    }
}
like image 118
neodim Avatar answered Oct 25 '22 22:10

neodim


I've used the following for years. Don't know if there a less "dodgy" way to achieve it in more up to date .Net frameworks though:

public void PreserveStackTrace(Exception ex)
{
    MethodInfo preserve = ex.GetType().GetMethod("InternalPreserveStackTrace",
                                                 BindingFlags.Instance | BindingFlags.NonPublic);
    preserve.Invoke(ex,null);
}

To use this:

[WebMethod]
public void ExceptionTest()
{
    try
    {
        throw new Exception("An Error Happened");
    }
    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        PreserveStackTrace(ex);
        throw ex;
    }
}

Update: based on @dcastro's comment, I'd fancy an extension method in 4.5 (in < 4.5 it could still be an extension wrapping the method above):

public static void ReThrow(this Exception ex)
{
    var exInfo = ExceptionDispatchInfo.Capture(ex); 
    exInfo.Throw();
}

So you'd just have:

    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        ex.ReThrow();
    }
like image 20
Jon Egerton Avatar answered Oct 26 '22 00:10

Jon Egerton