多次尝试捕获还是一次?


76

通常,我会这样做:

try
{
    code

    code that might throw an anticipated exception you want to handle

    code

    code that might throw an anticipated exception you want to handle

    code
}
catch 
{

}

这样做有什么好处吗?

code

try
{
    code that might throw an anticipated exception you want to handle
}
catch
{
}

code

try
{
    code that might throw an anticipated exception you want to handle
}
catch
{
}

code

更新:

我最初问这个问题时是否引用了C#,但正如A. Levy所评论的那样,它可以应用于任何异常处理语言,因此我使标记反映了这一点。


7
您是否要在第一个错误发生时立即停止处理(第一个示例),或者即使一部分处理失败(另一个错误)也可以继续进行?
大卫·普拉特

2
@DLP-我希望它停止处理-我看到有人在你之后提到它。那是个很好的观点。
史蒂夫2010年

4
尽管您使用C#和.net对此进行了标记,但我认为它确实与语言无关。该问题适用于任何语言,但Java,C ++,JavaScript,OCaml,F#,Python,Clojure等除外。它也适用于Common Lisp和其他各种Lisps中的条件/重新启动系统。所以我想请您使这种语言不可知...不过您的来电。
A. Levy 2010年

Answers:


88

这取决于。如果要为特定错误提供特殊处理,请使用多个catch块:

try
{ 
    // code that throws an exception
    // this line won't execute
}
catch (StackOverflowException ex)
{
    // special handling for StackOverflowException 
}
catch (Exception ex)
{
   // all others
}

但是,如果要处理异常并继续执行,请将代码放在单独的try-catch块中:

try
{ 
    // code that throws an exception

}
catch (Exception ex)
{
   // handle
}

try
{ 
    // this code will execute unless the previous catch block 
    // throws an exception (re-throw or new exception) 
}
catch (Exception ex)
{
   // handle
}

4
+1(在第一个示例中突出显示)确保常规异常处理程序在声明中位于最后,以便您首先处理特定的异常,然后以通用方式处理控件之外的任何其他内容。
leeroya

如此处所述:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…,条件捕获的使用是非标准的,也不在标准轨道上。请勿在面向Web的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,并且将来的行为可能会更改。
JLavoie

16

如果我可以选择第二个,则可能会将其分为两个功能。


5
+1:我完全同意,尽管我可能会这样写:“如果我可以选择第二个,我会的。”,因为我认为这是在任何可能的时间做的正确事情……
Reed Copsey

11

两者都不用,只对特定的异常使用多个catch块(除非该块中只有一吨代码,并且只有几行可能会引发异常。在这种情况下,我将使用第二种方法)。


9

您正在以错误的方式思考。您需要在捕获块中做什么?如果您可以通过运行相同的代码任何可能的异常中恢复,则无论哪个操作引发了异常,请使用一个catch块。如果您需要根据抛出的操作执行不同的清理操作,请使用多个catch块。

另外,如果可以使用try / finally或RAII模式代替try / catch,则应该这样做。


4

我认为第二种方法更好,因为它可以使您更准确地捕获错误。

如果您的应用程序存在某种问题并且崩溃,那么将整个代码包装在一个大的try / catch块中也是不好的,但是由于您捕获了一个大型的通用执行,因此实际上可以正确处理它的机会较低。您应该在try catch中包含特殊的部分,例如读取文件或接受用户输入。这样你可以更好地处理这种观念


2

我更喜欢第二种方法-它使调试更加容易,错误处理更加准确,并且也很好地融入了单元测试。


2

我会选择第二个选项,但是每当看到此代码模式时,我的第一感觉就是考虑将其拆分为多个函数/方法。显然,是否这样做取决于代码在做什么;)


2

这取决于代码中发生的错误类型的性质。

  1. 如果您要处理的这些错误相同,请尝试一下...赶上那组代码。否则将太乏味。

  2. 如果错误需要不同的处理,则必须将其分开。

请勿对所有情况都采用单一方法。大部分时间是在上下文中指定的:)

您需要达到“良好/复杂”和“不良/简单”的平衡。您编写的代码越多,您就越不会陷入这种困境:)

编程愉快!


2
通常,用大写字母写整个句子的形式很差。但是最后,这是特定于上下文的
乔·菲利普斯

1

第二种方法。将可能引发异常的代码与其他代码分开-使该节更小且更易于管理,而不是包装所有代码,即使那些不会引发异常的代码也是如此。


1

有一段时间我们想向用户显示特定错误。

try{
   try{
      ... send message
   }
   catch(exception e){
    ...log error
    ...rethrow  send related error/show custom error
   }
   try{
       ...try to receive response
   }
   catch(exception e){
       ...show receive related error
   }
   //finally close the connection
   }finally{
        ...close connection
   }

-1

第二种方法,但理想情况下使用代码保护-如果捕获异常,则try / catch可能会非常昂贵。


2
在C#中尝试/捕获确实不是很昂贵,除非您实际上捕获了某些东西……
Reed Copsey 2010年

2
PS:我知道这个答案已有7年历史了,但想在2017年的背景下使用...。Try / Catch的性能影响大大超过了引用,并且想象中的性能提升从来都不是编写更好,更可靠的代码的好理由,尤其是当您意识到.NET出现时,您可以买到的最好的计算机是奔腾4 w / 1-2GB ram,今天我们有4个内核,超线程,速度是8倍以上,并且8-16GB RAM是标准配置。最重要的是,即使在相同的硬件上,.NET编译代码也比15年前更快。缓慢调用“尝试/捕获”是一个神话,它需要停止。
TravisO
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.