一次捕获多个异常?

时间:2020-03-06 14:44:57  来源:igfitidea点击:

不建议仅捕获System.Exception。相反,仅应捕获"已知"异常。

现在,这有时会导致不必要的重复代码,例如:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

我想知道:有没有一种方法可以捕获两个异常,并且只调用一次" WebId = Guid.Empty"调用?

给定的示例非常简单,因为它只是一个" GUID"。但是,请想象一下代码中多次修改对象的情况,如果其中一种操作以预期的方式失败,则我们想"重置""对象"。但是,如果有意外的例外,我仍然想将其提高。

解决方案

请注意,我确实找到了一种方法来执行此操作,但这看起来更像是The Daily WTF的资料:

catch (Exception ex)
{
    switch (ex.GetType().Name)
    {
        case "System.FormatException":
        case "System.OverflowException":
            WebId = Guid.Empty;
            break;
        default:
            throw;
    }
}

怎么样

try
{
    WebId = Guid.Empty;
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
}
catch (OverflowException)
{
}

捕获System.Exception并打开类型

catch (Exception ex)            
{                
    if (ex is FormatException || ex is OverflowException)
    {
        WebId = Guid.Empty;
        return;
    }

    throw;
}

@米歇尔

代码略有修改:

catch (Exception ex)
{
   Type exType = ex.GetType();
   if (exType == typeof(System.FormatException) || 
       exType == typeof(System.OverflowException)
   {
       WebId = Guid.Empty;
   } else {
      throw;
   }
}

字符串比较丑陋且缓慢。

不幸的是,因为我们需要使用异常过滤器来执行此操作,因此C不会公开MSIL的功能。 VB.NET确实具有此功能,例如

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

我们可以做的是使用匿名函数封装错误代码,然后在这些特定的catch块中调用它:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

catch (Exception ex)
{
    if (!(
        ex is FormatException ||
        ex is OverflowException))
    {
        throw;
    }
    Console.WriteLine("Hello");
}

可接受的答案似乎是可以接受的,除了CodeAnalysis / FxCop会抱怨它正在捕获一般异常类型这一事实。

另外,似乎" is"运算符可能会稍微降低性能。

CA1800:不必进行不必要的强制转换,而是"考虑测试'as'运算符的结果",但是,如果这样做的话,与单独捕获每个异常的情况相比,我们将编写更多的代码。

无论如何,这是我会做的:

bool exThrown = false;

try
{
    // Something
}
catch (FormatException) {
    exThrown = true;
}
catch (OverflowException) {
    exThrown = true;
}

if (exThrown)
{
    // Something else
}