简体   繁体   English

在同一个 catch 块中捕获两个异常?

[英]Catch two exceptions in the same catch block?

I have a method that can throw two different exceptions, CommuncationException and SystemException .我有一个方法可以抛出两个不同的异常, CommuncationExceptionSystemException In both cases I do the same three-line code block.在这两种情况下,我都使用相同的三行代码块。

try {
 ...
}

catch (CommunicationException ce) {
   ...
}

catch {SystemExcetion se) {
   ... 
}

Is there any possibility to do it like that?有没有可能那样做?

try {
   ...
}

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

Then I would not have to write this much code.那样我就不用写这么多代码了。 I know I could extract the exception handling to a private method, but since the code is only 3 lines long, the method definition would take more code than the body itself.我知道我可以将异常处理提取到一个私有方法中,但是由于代码只有 3 行,方法定义将比主体本身占用更多的代码。

If you can upgrade your application to C# 6 you are lucky. 如果您可以将您的应用程序升级到C#6,那么您很幸运。 The new C# version has implemented Exception filters . 新的C#版本已经实现了Exception过滤器 So you can write this: 所以你可以这样写:

catch (Exception ex) when (ex is CommunicationException || ex is SystemException) {
    //handle it
}

Some people think this code is the same as 有些人认为这段代码是一样的

catch (Exception ex) {                
    if (ex is CommunicationException || ex is SystemException) {
        //handle it
    }
    throw;
}

But it´s not. 但事实并非如此。 Actually this is the only new feature in C# 6 that is not possible to emulate in prior versions. 实际上,这是C#6中唯一一个在以前版本中无法模拟的新功能。 First, a re-throw means more overhead than skipping the catch. 首先,重新投掷意味着比跳过捕获更多的开销。 Second, it is not semantically equivalent. 其次,它在语义上不等同。 The new feature preserves the stack intact when you are debugging your code. 在调试代码时,新功能可以保持堆栈完好无损。 Without this feature the crash dump is less useful or even useless. 如果没有此功能,崩溃转储就不那么有用甚至无用了。

See a discussion about this on CodePlex . 请参阅CodePlex上有关此问题讨论 And an example showing the difference . 一个显示差异例子

In fact, you could catch only SystemException and it would handle CommunicationException too, because CommunicationException is derived from SystemException 实际上,您只能捕获SystemException ,它也会处理CommunicationException ,因为CommunicationException是从SystemException派生的

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

Unfortunately, there is no way. 不幸的是,没有办法。 The syntax you used is invalid and a fall through like in a switch-statement isn't possible either. 您使用的语法无效,并且无法像在switch语句中那样掉头。 I think you need to go with the private method. 我认为你需要使用私有方法。

A little hacky work-around would be something like this: 一个小的hacky解决方案将是这样的:

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

You need to decide for yourself if this makes any sense. 你需要自己决定这是否有意义。

No, you can't do it that way. 不,你不能这样做。 The only way i know of is to catch a generic Exception and then check what type it is: 我知道的唯一方法是捕获一般的异常,然后检查它是什么类型:

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

What about 关于什么

try {


...
}

catch (CommunicationException ce) {
   HandleMyError(ce);
}

catch {SystemExcetion se) {
   HandleMyError(se);
}

private void HandleMyError(Exception ex)
{
// handle your error
}

Possible Duplicate of 可能重复

Catch multiple exceptions at once? 一次捕获多个异常?

I quote the answer here: 我在这里引用答案:

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

Dragging this one up from the depths of history as it happened to pop up in some search results.将它从历史深处拖上来,因为它恰好出现在某些搜索结果中。

With the advent of C# 7.0 (which arrived in 2017 with VS2017, .net framework 4.7 and do.net core 2.0) you can now do things like this:随着 C# 7.0(2017 年与 VS2017、.net 框架 4.7 和 do.net 核心 2.0 一起推出)的出现,您现在可以执行以下操作:

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

Since you're doing the same for both type of exceptions, you could just go: 既然你对两种类型的异常做了同样的事情,你可以去:

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

Only catch explicit Exception types if you need to do something unique for it. 如果你需要为它做一些独特的事情,只捕获显式的Exception类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM