在同一个Catch块中捕获两个异常

本文关键字:两个 异常 Catch 同一个 | 更新日期: 2023-09-27 17:49:26

我有一个方法,可以抛出两个不同的异常,CommuncationExceptionSystemException。在这两种情况下,我都使用了相同的三行代码块。

try {
 ...
}
catch (CommunicationException ce) {
   ...
}
catch {SystemExcetion se) {
   ... 
}

有可能那样做吗?

try {
   ...
}
catch (CommunicationException ce, SystemException se) {
   ...
}

那么我就不用写这么多代码了。我知道我可以将异常处理提取到一个私有方法,但由于代码只有3行长,方法定义将比主体本身占用更多的代码。

在同一个Catch块中捕获两个异常

如果你可以升级你的应用程序到c# 6,你是幸运的。新的c#版本实现了Exception过滤器。所以你可以这样写:

catch (Exception ex) when (ex is CommunicationException || ex is SystemException) {
    //handle it
}
有些人认为这段代码和 是一样的
catch (Exception ex) {                
    if (ex is CommunicationException || ex is SystemException) {
        //handle it
    }
    throw;
}

但它不是。实际上,这是c# 6中唯一一个在以前的版本中无法模拟的新特性。首先,重掷意味着比跳过接球更大的开销。其次,它在语义上不等同。在调试代码时,新特性保留了堆栈的完整性。如果没有这个特性,崩溃转储就不那么有用,甚至毫无用处。

查看CodePlex上关于这个的讨论。还有一个例子来说明它们的区别

事实上,您只能捕获SystemException,它也可以处理CommunicationException,因为CommunicationException派生自SystemException

catch (SystemException se) {
   ... //this handles both exceptions
}

不幸的是,没有办法。您使用的语法是无效的,并且不可能像在switch语句中那样失败。我认为你应该使用private方法。

一个简单的变通方法是这样的:

var exceptionHandler = new Action<Exception>(e => { /* your three lines */ });
try
{
    // code that throws
}
catch(CommuncationException ex)
{
    exceptionHandler(ex);
}
catch(SystemException ex)
{
    exceptionHandler(ex);
}

你需要自己决定这是否有意义

不行,你不能那样做。我知道的唯一方法是捕获一个泛型异常,然后检查它是什么类型:

try
{
   ...
}
catch(Exception ex)
{
   if(ex is CommunicationException || ex is SystemException)
   {
      ...
   }
   else
   {
     ... // throw; if you don't want to handle it
   }
}

try {

...
}
catch (CommunicationException ce) {
   HandleMyError(ce);
}
catch {SystemExcetion se) {
   HandleMyError(se);
}
private void HandleMyError(Exception ex)
{
// handle your error
}

可能的副本

一次捕获多个异常?

我在这里引用答案:

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

把这个从历史的深处拖上来,因为它碰巧出现在一些搜索结果中。

随着c# 7.0的出现(它在2017年与VS2017、。net框架4.7和。net core 2.0一起出现),你现在可以做这样的事情:

try {
   ...
}
catch (Exception e) when (e is CommunicationException || e is SystemException) {
   ...
}

由于您对两种类型的异常都做了相同的处理,因此您可以这样做:

try
{
    //do stuff
}
catch(Exception ex)
{
    //normal exception handling here
}

只有当你需要为它做一些独特的事情时才捕捉显式异常类型