这是“throw”和“throw ex”之间有区别</a>的后续问题吗?
有没有办法在不重置堆栈跟踪的情况下提取新的错误处理方法?
[编辑] 我将同时尝试“内部方法”和 Earwicker 提供的另一个答案,看看哪个可以更好地标记答案。
在 .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.
}
}
是的; 这就是 InnerException 属性的用途。
catch(Exception ex)
{
throw new YourExceptionClass("message", ex);
}
这将允许您添加自己的逻辑,然后抛出您自己的异常类。YourExceptionClass 实例的 StackTrace 将来自此代码块,但 InnerException 将是您捕获的异常,它之前有 StackTrace。
不知道你是不是这个意思,但我在你的另一个问题中的建议是解决这个问题。
如果您的处理程序返回一个布尔值是否处理了异常,您可以在您的 catch 子句中使用它:
catch (Exception ex) {
if (!HandleException(ex)) {
throw;
}
}
您不想使用原始堆栈跟踪创建新异常。这是误导,因为该堆栈跟踪没有创建新的异常。
但是,您可以将原始异常作为“InnerException”放入新异常中。那会做你正在寻找的吗?
您是否捕获了想要更仔细过滤的异常,以便您可以改变主意,决定不处理它们并重新抛出它们?
如果您想对此非常小心,那并不是一个好主意。最好一开始就不要捕获异常。原因是给定的try/catch
处理程序不应该决定为finally
它不期望看到的异常运行嵌套块。例如,如果有一个NullReferenceException
,继续执行任何代码可能是一个非常糟糕的主意,因为它可能会导致另一个这样的异常被抛出。finally
块只是代码,就像任何其他代码一样。一旦第一次捕获到异常,finally
堆栈上的任何块try/catch
都将被执行,到那时为时已晚 - 可能会生成另一个异常,这意味着原始异常丢失了。
这意味着(在 C# 中)您必须仔细catch
为要捕获的所有异常类型编写一个单独的处理程序。这也意味着您只能按异常类型进行过滤。这有时是很难遵循的建议。
应该可以通过其他方式过滤异常,但在 C# 中则不然。但是,这在 VB.NET 中是可能的,并且 BCL 本身通过在 VB.NET 中编写少量代码来利用这一点,因此它可以以更方便的方式过滤异常。