检查内部异常的类型
本文关键字:类型 异常 内部 检查 | 更新日期: 2023-09-27 18:30:46
在我的代码中,我遇到了抛出System.Reflection.TargetInvocationException
的情况。在一个特定的情况下,我知道我想要如何处理根异常,但我想抛出所有其他异常。我可以想到两种方法,但我不确定哪种更好。
1.
try
{
//code
}
catch (System.Reflection.TargetInvocationException ex)
{
if (typeof(ex.InnerException) == typeof(SpecificException))
{
//fix
}
else
{
throw ex.Innerexception;
}
}
阿拉伯数字。
try
{
//code
}
catch (System.Reflection.TargetInvocationException ex)
{
try
{
throw ex.InnerException;
}
catch (SpecificException exSpecific)
{
//fix
}
}
我知道抛出异常通常很慢,所以我觉得第一种方法可能会更快。或者,有没有我没有想到的更好的方法?
您提出的每个解决方案都有自己的问题。
第一种方法检查内部异常的类型是否与预期的类型完全一致。这意味着派生类型将不匹配,这可能不是您想要的。
第二种方法使用当前堆栈位置覆盖内部异常的堆栈跟踪,如 Dan Puzey 所述。销毁堆栈跟踪可能会销毁修复 bug 所需的一个线索。
解决方案基本上是 DarkGray 发布的内容,其中包含 Nick 的建议和我自己的附加建议(在else
中):
try
{
// Do something
}
catch (TargetInvocationException ex)
{
if (ex.InnerException is SpecificException)
{
// Handle SpecificException
}
else if (ex.InnerException is SomeOtherSpecificException)
{
// Handle SomeOtherSpecificException
}
else
{
throw; // Always rethrow exceptions you don't know how to handle.
}
}
如果要重新引发无法处理的异常,请不要throw ex;
,因为这将覆盖堆栈跟踪。请改用保留堆栈跟踪的throw;
。它基本上意味着"我实际上不想输入这个catch
条款,假装我从未抓住例外"。
更新:C# 6.0 通过异常筛选器提供了更好的语法:
try
{
// Do something
}
catch (TargetInvocationException ex) when (ex.InnerException is SpecificException)
{
// Handle SpecificException
}
catch (TargetInvocationException ex) when (ex.InnerException is SomeOtherSpecificException)
{
// Handle SomeOtherSpecificException
}
您的#2绝对是一个有趣的解决方案!
不过,您确实要小心:TargetInvocationException
在第一次捕获InnerException
时通常会被另一个组件抛出。 如果您throw ex.InnerException
,您将销毁它包含的某些信息(例如堆栈跟踪),因为您要从其他位置重新抛出它。
所以在你提出的两个中,我绝对建议使用#1。 我不知道您拥有的结构中有替代方案。 但是,InnerException 最初将被抛出到其他地方 - 值得研究是否有一个更优雅的地方来处理这个失败,更接近抛出异常的位置。
try
{
//code
}
catch (System.Reflection.TargetInvocationException ex)
{
if (ex.InnerException is SpecificException)
{
//fix
}
else
{
throw ex.InnerException;
}
}
或
try
{
//code
}
catch (System.Reflection.TargetInvocationException ex)
{
SpecificException spExc = ex.InnerException as SpecificException;
if (spExc != null)
{
bla-bla spExc
}
else
{
throw ex.InnerException;
}
}
或
try
{
//code
}
catch (System.Reflection.TargetInvocationException ex)
{
if (ex.InnerException.GetType() == typeof(SpecificException))
{
//fix
}
else
{
throw ex.InnerException;
}
}