我想编写一个处理异常的方法,该方法将在catch
块中调用。根据传递的异常的类型,异常要么作为新异常的内部异常传递,要么只是重新引发。在第二种情况下如何保留堆栈跟踪?
例:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex)
{
HandleException(ex);
}
}
private void HandleException(Exception ex)
{
if(ex is SpecificException)
throw ex; //will not preserve stack trace...
else
throw new SpecificException(ex);
}
我不想做的是,因为该模式在很多地方重复并且不会有因式分解:
try
{
SomeWorkMethod();
}
catch(Exception ex)
{
if(ex is SpecificException)
throw;
else
throw new SpecificException(ex);
}
在不指定异常的情况下使用throw
以保留堆栈跟踪。这只能在catch
块内完成。您可以做的是从HandleException
返回而不抛出原始异常,然后立即使用 throw
:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex)
{
HandleException(ex);
throw;
}
}
private void HandleException(Exception ex)
{
if(ex is SpecificException)
return;
else
throw new SpecificException(ex);
}
只要只使用 is
对异常进行分类,首选方法是两个 catch 块:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch (SpecificException)
{
throw;
}
catch(Exception ex)
{
throw new SpecificException(ex);
}
}
在 C# 6.0 中,还可以使用 when
让异常消失:
public void TestMethod()
{
try
{
// can throw an exception specific to the project or a .Net exception
SomeWorkMethod()
}
catch(Exception ex) when (!(ex is SpecificException))
{
throw new SpecificException(ex);
}
}
实际上,在 中有一个非常好的方法可以做到这一点。Net4.5 使用 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture
:
void Main()
{
try
{
throw new Exception(); //appears to be thrown from here
}
catch(Exception ex)
{
ThrowEx(ex);
}
}
public void ThrowEx(Exception ex)
{
if(someCondition)
{
//we're in the scope of a `catch` and the exception
//is "active", so the exception with original stack-trace
//can be re-thrown with
ExceptionDispatchInfo.Capture(ex).Throw();
//the following line is unreachable, but the compiler doesn't realise
//so we can "tell" the compiler that this branch ends in an exception
//and avoid having to return anything in the non-void case
throw new Exception();
}
}
也许你可以试试这个。
if(ex.Gettype() == typeof(SpecificException))