【问题标题】:Multiple-exception catches多异常捕获
【发布时间】:2012-06-26 16:12:34
【问题描述】:

是否可以在同一个catch 块中捕获多个异常?

try
{   }
catch(XamlException s | ArgumentException a)
{   }

【问题讨论】:

  • 该语法不是 C# 标准的一部分,因此您最终会遇到编译器错误 :)
  • 虽然这可能不是您向我们展示的实际代码,但 ArgumentException 派生自 SystemException,因此 catch (SystemException) 足以捕获这两种类型。当然,如果您想检查不正确的参数,您仍然需要强制转换,但如果您需要那么多信息,那么单独的 catch 块可能更有意义。最后,无论如何,你真的不应该抓到ArgumentException;这意味着你做错了什么,所以只要解决问题而不是忽视它。
  • blogs.msdn.com/b/toub/archive/2004/03/05/84698.aspx,用于处理过滤器和多个异常。即使 VB.NET/F# 允许这样的事情,这也是一种技巧,因为 CLR 不直接支持它。

标签: c# exception exception-handling


【解决方案1】:

是的。如果你捕获了一个超类,它也会捕获所有的子类:

try
{
    // Some code
}
catch(Exception e)
{
    // ...
}

如果这捕获的数量超出了您的预期,那么您可以通过测试它们的类型来重新抛出您不打算捕获的异常。如果这样做,请小心使用throw; 语法,而not throw e;。后一种语法破坏了堆栈跟踪信息。

但是你不能使用你建议的语法来捕捉两种不同的类型。

【讨论】:

  • throw;throw e; 之间指定是个好主意。只是为了进一步澄清,后者不好的原因是因为它将调用堆栈重置为源自 catch 块,而不是最初引发异常的位置。我确定你知道这一点,我只是想为其他人澄清一下:)
  • 即使 throw e; 并没有真正按预期工作。它保存了堆栈,但它擦除了行号。举个例子看看this answer我在SO上发帖。
  • @Adriano:你的意思是“Even throw;”吗?
【解决方案2】:

没有你问的那么简洁。一种方法是捕获所有异常并专门处理这两个:

catch(Exception e)
{   
  if((e is SystemException) || (e is ArgumentException))
     // handle, rethrow, etc.
  else
     throw;
}

【讨论】:

    【解决方案3】:

    虽然不是 C# 大师,但这是任何 oop 语言的标准。

        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific:
        catch (InvalidCastException e) { out_one(e); }
        catch (ArgumentNullException e) { out_two(e); }
    
        // Least specific - anything will get caught
        // here as all exceptions derive from this superclass
        catch (Exception e)
        {
            // performance-wise, this would be better off positioned as
            // a catch block of its own, calling a function (not forking an if)
            if((e is SystemException) { out_two(); }
            else { System..... }
        }
    

    【讨论】:

      【解决方案4】:

      在 vb.net 中,可以说Catch Ex As Exception When IsMyException(Ex),其中IsMyException 是任何所需的函数,它检查Ex 并决定是否捕获它。在任何内部Finally 块运行之前 确定是否捕获Ex。不幸的是,C# 的制造者不喜欢允许自定义异常过滤器的想法,可能是因为它会用特定于平台的细节污染语言(大多数平台不支持 .net 样式的异常过滤器)。因此,在 C# 中最好的希望是执行以下操作:

      无效 HandleThisOrThatException(BaseTypeOfThisThatTheOtherException) { ... } ... // 捕获 ThisException 或 ThatException,但不捕获 TheOtherException 捕捉 (ThisException ex) {HandleThisOrThatException(ex);} 捕捉(ThatException ex){HandleThisOrThatException(ex);}

      【讨论】:

        【解决方案5】:

        这是一个不好的例子,因为任何ArgumentException 也是SystemException,所以捕获所有 SystemExceptions 也会隐含地得到ArgumentExceptions。

        【讨论】:

        • 在超类异常之前捕获特定异常的要点是,您有更高级别的控制。上面的示例是随机复制的异常名称,OP 要求语义。
        猜你喜欢
        • 2020-05-10
        • 2013-05-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 2013-01-31
        • 1970-01-01
        相关资源
        最近更新 更多