如何在不重置堆栈跟踪的情况下抛出异常?

dan*_*die 21 .net c# error-handling exception-handling stack-trace

这是一个后续问题,"throw"和"throw ex"之间有区别吗?

有没有办法提取新的错误处理方法而不重置堆栈跟踪?

[编辑] 我将尝试"内部方法"和Earwicker提供的另一个答案,看看哪一个可以更好地标记答案.

Ada*_*son 44

是; 这就是InnerException属性的用途.

catch(Exception ex)
{
    throw new YourExceptionClass("message", ex);
}
Run Code Online (Sandbox Code Playgroud)

这将允许您添加自己的逻辑,然后抛出自己的异常类.YourExceptionClass实例的StackTrace将来自此代码块,但InnerException将是您捕获的异常,使用之前的StackTrace.

  • 这种方法在实践中的缺点是许多错误日志只包含最顶层异常的详细信息。[这种方法](http://stackoverflow.com/a/12619055/24874) 避免了这种情况。 (2认同)

Zar*_*rat 41

使用.NET Framework 4.5,现在有一个ExceptionDispatchInfo支持这种确切的场景.它允许捕获完整的异常并从其他地方重新抛出它而不会覆盖包含的堆栈跟踪.

由于评论请求而导致的代码示例

using System.Runtime.ExceptionServices;

class Test
{
    private ExceptionDispatchInfo _exInfo;

    public void DeleteNoThrow(string path)
    {
        try { File.Delete(path); }
        catch(IOException ex)
        {
            // Capture exception (including stack trace) for later rethrow.
            _exInfo = ExceptionDispatchInfo.Capture(ex);
        }
    }

    public Exception GetFailure()
    {
        // You can access the captured exception without rethrowing.
        return _exInfo != null ? _exInfo.SourceException : null;
    }

    public void ThrowIfFailed()
    {
        // This will rethrow the exception including the stack trace of the
        // original DeleteNoThrow call.
        _exInfo.Throw();

        // Contrast with 'throw GetFailure()' which rethrows the exception but
        // overwrites the stack trace to the current caller of ThrowIfFailed.
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @KonstantinSpirin:认为可用的方法和MSDN文档非常明显,但无论如何都添加了一些示例代码,无需点击MSDN即可获得概述. (4认同)
  • 有趣但很高兴看到一些代码示例 (3认同)

Luc*_*ero 27

不确定你的意思是,但我在你的另一个问题中的建议是解决这个问题.

如果你的处理程序返回一个布尔值,无论是否处理了异常,你可以在catch子句中使用它:

catch (Exception ex) {
  if (!HandleException(ex)) {
    throw;
  }
}
Run Code Online (Sandbox Code Playgroud)


Bri*_*sio 5

您不希望使用原始堆栈跟踪创建新异常.这是误导,因为堆栈跟踪没有创建新的异常.

但是,您可以将原始异常作为"InnerException"放在新异常中.这会做你想要的吗?