Catch two exceptions in the same catch block?
我有一个方法可以抛出两个不同的异常:CommuncationException和SystemException。在这两种情况下,我都执行相同的三行代码块。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | try {...
 }
 
 catch (CommunicationException ce) {
 ...
 }
 
 catch {SystemExcetion se) {
 ...
 }
 | 
有没有可能这样做?
| 12
 3
 4
 5
 6
 7
 
 | try {...
 }
 
 catch (CommunicationException ce, SystemException se) {
 ...
 }
 | 
那我就不用写这么多代码了。我知道我可以将异常处理提取到私有方法中,但是由于代码只有3行长,所以方法定义需要的代码比主体本身要多。
		
		
- 不管怎样,我不完全确定你是否愿意。难道你不会最终还是写代码来区分例外情况吗——if (ce...) else (se...)。最后,它可能看起来更凌乱。
- 这里也存在类似的问题stackoverflow.com/questions/136035/…但是您将捕获基本的Exception,您仍然需要编写代码来检查CommunicationException或SystemException的派生类型…它比你现有的catch {} catch {}更多,所以不值得麻烦。
- @詹姆斯怀斯曼不,我不需要一个如果/否则,因为这两个例外处理是完全相同的。
 
	 
如果你能把你的应用升级到C 6,你就很幸运了。新的C版本实现了异常过滤器。所以你可以这样写:
| 12
 3
 
 | catch (Exception ex)  when ( ex is  CommunicationException ||  ex is  SystemException) {
    //handle it
} | 
有些人认为此代码与
| 12
 3
 4
 5
 6
 
 | catch (Exception ex) {                
    if ( ex is  CommunicationException ||  ex is  SystemException) {
        //handle it
    }
    throw;
} | 
但事实并非如此。实际上,这是C 6中唯一不可能在以前版本中模拟的新功能。首先,再掷意味着比跳过捕获更多的开销。第二,它在语义上不是等价的。在调试代码时,新特性会保持堆栈的完整性。如果没有这个特性,崩溃转储就不那么有用,甚至是无用的。
请参阅关于CodePlex的讨论。以及一个显示差异的例子。
		
		
- 正如上面的投票所反映的,这是对这个问题的更好的回答。接受的答案正确地解决了给定的代码示例,但没有回答所问的问题。
- 这应该是公认的答案
 
	 
实际上,你只能抓到SystemException,它也能处理CommunicationException,因为CommunicationException是从SystemException派生出来的。
| 12
 3
 
 | catch (SystemException se) {... //this handles both exceptions
 }
 | 
		
		
- +1:在他具体的情况下,这就是我们要走的路。抓得好!
- 是的,这是可能的,但这也是一个好的做法吗?我也会捕获所有其他的子类而不明确地知道它?
- 无论如何都要这样做,因为您已经捕获了SystemException。
- 哦,是的;)我从来没想过。那么,第一次捕获是相当无用的。
- 如果执行的代码完全相同:是的,确实如此。
- 不,这不是一个好的实践,因为它会捕获大量的异常。但正如丹尼尔提到的,如果不是交流,你已经这样做了。例外:)
- 是的,这段代码并不是最好的,因为它捕获各种系统异常,而不仅仅是所需的两个异常。你可能希望所有其他的都不要在这个尝试捕获中被捕获!
 
	 
不幸的是,没有办法。您使用的语法无效,也不可能像switch语句那样执行fall through。我认为你需要使用私人方法。
一个小小的黑客工作是这样的:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | var exceptionHandler = new  Action< Exception>( e => { /* your three lines */ });
try
{
    // code that throws
}
catch( CommuncationException ex)
{ 
    exceptionHandler( ex);
}
catch( SystemException ex)
{ 
    exceptionHandler( ex);
} | 
你需要自己决定这是否有意义。
		
		
- 他不想那样做:p
- 是的,他在哪里说的?;-)他只是不想创建私有方法,因为它创建了代码开销。这个开销在我的样本中大大减少了。但不管怎样,我的主要答案是,他就是不能做他想做的事…我没有给他提供一个"解决方案",他在这个问题上已经被驳回了。
- 我知道,只是笑了一下:)
 
	 
不,你不能那样做。我知道的唯一方法是捕获一个泛型异常,然后检查它是什么类型:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | try
{
   ...
}
catch(Exception ex)
{
   if( ex is  CommunicationException ||  ex is  SystemException)
   {
      ...
   }
   else
   {
     ... // throw; if you don't want to handle it
   }
} | 
		
		
- 这将更改异常的调用堆栈。不是你想要的。
- 如果我只是在else语句中使用throw,那么这为什么会更改调用堆栈?
- 看看这里:stackoverflow.com/questions/515265/&hellip;
- 非常感谢,我一直认为我应该避免使用throw ex
- 没错,您应该避免使用"throw ex;",但这不是他正在做的,他使用"throw;"保留原始异常信息;
 
	 
可能的副本
一次捕获多个异常?
我引用这里的答案:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 |  catch (Exception ex)            
       {                
           if ( ex is  FormatException || 
               ex is  OverflowException)
           { 
               WebId =  Guid.Empty;
               return;
           }
           else
           {
               throw;
           }
       } | 
		
		
- 我不同意那个问题中提供的解决方案,因为我不支持亚历克森的回答。这确实和亚历克森给出的答案一样……
- @丹尼尔:嗯。很高兴知道它改变了调用堆栈,可能不能正常工作。
- 在这个解决方案中,重要的是它重新抛出所有的REST类型异常!
 
	 
怎么样
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | try {
 
 ...
 }
 
 catch (CommunicationException ce) {
 HandleMyError(ce);
 }
 
 catch {SystemExcetion se) {
 HandleMyError(se);
 }
 
 private void HandleMyError(Exception ex)
 {
 // handle your error
 }
 | 
既然您对这两种类型的异常都做了相同的操作,那么您只需执行以下操作:
| 12
 3
 4
 5
 6
 7
 8
 
 | try{
 //do stuff
 }
 catch(Exception ex)
 {
 //normal exception handling here
 }
 | 
只有在需要为显式异常类型做一些独特的事情时才捕获它。