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

Rob*_*J1M 8 .net c# throw

您显然能够在不丢弃.NET中的堆栈跟踪的情况下重新抛出异常.

但它似乎没有起作用.

因此我遵循的基本用法是:

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

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

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

它为什么这样做?我该怎么做?

neo*_*dim 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但是您失去了原始异常类型(尽管在您的示例中原始异常和重新引发的异常都是异常类型)。ExceptionDispatchInfo.Capture(ex).Throw() 抛出原始异常类型的异常。 (3认同)

Jon*_*ton 5

我已经使用以下多年了。但是,不知道是否有更少的“狡猾”方法可以在最新的.Net框架中实现:

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

要使用此功能:

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

更新:基于@dcastro的评论,我想在4.5中使用扩展方法(在<4.5中,它仍然可以是包装上述方法的扩展):

public static void ReThrow(this Exception ex)
{
    var exInfo = ExceptionDispatchInfo.Capture(ex); 
    exInfo.Throw();
}
Run Code Online (Sandbox Code Playgroud)

因此,您将拥有:

    catch (Exception ex)
    {
        evlWebServiceLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        ex.ReThrow();
    }
Run Code Online (Sandbox Code Playgroud)

  • 如今,您可以使用`var exInfo = ExceptionDispatchInfo.Capture(ex); exInfo.Throw();` (4认同)