我了解ExceptionDispatchInfo.Capture(e).Throw()
的值(value)(保留了原始的堆栈跟踪),但是,尽早使用Capture
并传递ExceptionDispatchInfo
与仅传递捕获的Exception
相比有什么好处?
作为一个具体的例子,比较
static Exception CaptureException(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return e;
}
}
public void Test1()
{
ExceptionDispatchInfo.Capture(CaptureException(
() => throw new IOException("Test")))
.Throw();
}
和
static ExceptionDispatchInfo CaptureDispatchInfo(Action action)
{
try
{
action();
return null;
}
catch (Exception e)
{
return ExceptionDispatchInfo.Capture(e);
}
}
public void Test2()
{
CaptureDispatchInfo(() => throw new IOException("Test")).Throw();
}
,两者都给出基本相同的堆栈跟踪信息(这与
async
的变体类似。)。因此,我真的不知道为什么ExceptionDispatchInfo
类存在,而不仅仅是组合的ExceptionDispatchInfo.Capture(e).Throw()
方法。 最佳答案
您假设异常是不可变的。事实并非如此-异常的StackTrace在重新抛出时会更改。ExceptionDispatchInfo.Capture
的目的是在某个时间点捕获潜在变异的异常的StackTrace:
void Foo() => throw new InvalidOperationException ("foo");
Exception original = null;
ExceptionDispatchInfo dispatchInfo = null;
try
{
try
{
Foo();
}
catch (Exception ex)
{
original = ex;
dispatchInfo = ExceptionDispatchInfo.Capture (ex);
throw ex;
}
}
catch (Exception ex2)
{
// ex2 is the same object as ex. But with a mutated StackTrace.
Console.WriteLine (ex2 == original); // True
}
// So now "original" has lost the StackTrace containing "Foo":
Console.WriteLine (original.StackTrace.Contains ("Foo")); // False
// But dispatchInfo still has it:
try
{
dispatchInfo.Throw ();
}
catch (Exception ex)
{
Console.WriteLine (ex.StackTrace.Contains ("Foo")); // True
}