19

在我的代码中,我遇到了System.Reflection.TargetInvocationException抛出 a 的情况。在一种特定情况下,我知道我想如何处理根异常,但我想抛出所有其他异常。我可以想到两种方法,但我不确定哪种方法更好。

1.

try
{
    //code
}
catch (System.Reflection.TargetInvocationException ex)
{
    if (typeof(ex.InnerException) == typeof(SpecificException))
    {
        //fix
    }
    else
    {
        throw ex.Innerexception;
    }
}

2.

try
{
    //code
}
catch (System.Reflection.TargetInvocationException ex)
{
    try
    {
        throw ex.InnerException;
    }
    catch (SpecificException exSpecific)
    {
        //fix
    }
}

我知道抛出异常通常很慢,所以我觉得第一种方法可能会更快。或者,有没有我没有想到的更好的方法?

4

3 回答 3

37

您提出的每个解决方案都有自己的问题。

第一种方法检查内部异常的类型是否正是您所期望的类型。这意味着派生类型将不匹配,这可能不是您想要的。

正如 Dan Puzey 所提到的,第二种方法用当前堆栈位置覆盖内部异常的堆栈跟踪。销毁堆栈跟踪可能会破坏您修复错误所需的一条线索。

解决方案基本上是 DarkGray 发布的,有尼克的建议和我自己的附加建议(在 中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;which 保留堆栈跟踪。它的基本意思是“我实际上并不想输入这个catch子句,假装我从未发现异常”。

更新: C# 6.0 通过Exception Filters提供了更好的语法:

try
{
    // Do something
}
catch (TargetInvocationException ex) when (ex.InnerException is SpecificException)
{
    // Handle SpecificException
}
catch (TargetInvocationException ex) when (ex.InnerException is SomeOtherSpecificException)
{
    // Handle SomeOtherSpecificException
}
于 2012-04-12T09:20:22.363 回答
1

您的#2 绝对是一个有趣的解决方案!

不过,您确实需要小心:当它第一次被捕获TargetInvocationException时,它通常会被另一个组件抛出。如果您要销毁它包含的某些信息(例如堆栈跟踪),因为您要从不同的位置重新抛出它。 InnerExceptionthrow ex.InnerException

所以在你提出的两个中,我肯定会建议使用#1。我不知道您所拥有的结构中的替代方案。但是,InnerException 最初会在其他地方抛出 - 值得研究是否有更优雅的地方来处理这个失败,更接近抛出异常的地方。

于 2012-04-12T09:12:46.097 回答
-2
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; 
    } 
} 
于 2012-04-12T09:09:23.570 回答