在堆栈跟踪中使用正确的行号重新抛出异常

时间:2014-02-06 10:20:46

标签: c# .net throw

您显然能够重新抛出异常,而不会丢弃.NET中的堆栈跟踪。

然而它似乎没有起作用。

我遵循的基本用法是:

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

问题是,throw;行的行中的行号,而不是原始的throw new行。

我在一个简单的exe项目中测试过,没有登录到Windows日志行。它没有任何区别,堆栈跟踪总是包含错误的行号,使其不太有用。

为什么这样做? 我该如何正确地做到这一点?

2 个答案:

答案 0 :(得分:6)

如果将原始异常置于内部异常中,则不会丢失原始异常。

[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);
    }
}

答案 1 :(得分:5)

我已经使用了以下几年了。不知道是否有更少“狡猾”的方式在更新的.Net框架中实现它:

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

要使用它:

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

更新:根据@ dcastro的评论,我想看4.5中的扩展方法(< 4.5它仍然可以是包含上述方法的扩展名):

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

所以你只有:

    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        ex.ReThrow();
    }