C#中的exception处理:多次尝试/捕获与一次

每种方法有多个try{} catch{}语句是一种好习惯吗?

在我看来,最好让每个方法只处理一个任务。 因此,您很少需要在单个方法中拥有多个try / catch块。 但是,我没有看到任何问题。

正如Lisa所指出的那样,你应该捕获特定的exception,并且捕获方法可以实际处理的exception。

最好有一次try / catch多次捕获以不同方式处理每种类型的Exception。

如果您知道事先可能发生的exception类型,那么您可以尝试一次并捕获每个exception,如果您想以不同方式处理它们。 例如:

 try { // a bunch of risky code } catch (SpecificException1 ex1) { // handle Specific Exception 1 } catch (SpecificException2 ex2) { // handle Specific Exception 2 } catch (SpecificException3 ex3) { // handle Specific Exception 3 } catch (Exception ex) { // handle an exception that isn't specific } 

IMO如果您知道可能发生的exception,则不应使用try … catch来获取错误。

不要用例外编程….所以我不认为倍数是个好主意。

一般来说,我总是比catch更多。 通常情况下,除了exception之外没有太多具体的内容,所以让它冒泡。 但finally确保你可以干净利落地关闭等等。

对于复杂的生产级场景,拥有多个try-catch语句是一种可怕的做法,将这些语句置于业务逻辑中是非常不灵活的做法。

Windows云计算团队(他们的代码必须高效可靠)似乎坚持使用exception处理操作策略 。

这段代码是一个更好的替代品:

 // perform action within the policy policy.Do(() => repository.AddMessages(someMessages)); 

虽然较旧的代码块看起来像:

 try { repository.AddMessages(someMessages); } catch (Exception1 ex) { // dosomething... } catch (Exception2 ex) { // second handler } catch (Exception3 ex) { // third handler } 

或(这是Microsoft Enterprise Library在硬编码操作策略中提供可配置exception处理程序的方式):

 try { repository.AddMessages(someMessages); } catch (Exception ex) { bool rethrow = ExceptionPolicy .HandleException(ex, "Global Policy"); if (rethrow) { throw; } } 

另外,如果您有操作策略 ,您可以告诉它(配置)记录,hibernate,重试某些类型的exception,而不是简单地失败或执行其他一些硬编码操作。

根据经验,每个方法都应该处理一个任务 – 这个最佳实践源自一个测试驱动的环境,这使得生成测试变得更加容易。 编写“上帝”程序的测试计划本身就更加困难。

因此,最佳做法是仅对可能失败的项目使用try {} catch {},并且仅在通常捕获有用处理的exception的位置使用。

不要使用单个try {} catch {}来包装方法的全部内容,从而消除对正确编码实践的责任。

处理exception是一项昂贵的操作 – 在必要时捕获它们并编写可防止其他地方发生exception的代码。 在某些情况下,防止exception本身并不简单,但可以使用try / catch有效地捕获和使用它 – 例如检查文件操作的排他性。

当你使用try / catch时做出有意识的决定,不要因为你可以扔掉它,这是懒惰的。 问自己“我在这里需要它吗?”,或“我可以使用更便宜和/或更结构化的方法来做到这一点吗?”。

即使每种方法有1次尝试/捕获也是不好的做法。

exception是完全发明的,因此我们可以编写更少的error handling代码,而不是像其他一些答案所暗示的那样。

在exception之前,您必须通过测试返回值来检查每行代码的成功,如果出现错误,则必须通过返回将其传递回调用堆栈。 这意味着每种方法都必须进行测试和返回。 发明了exception,因此方法不需要在整个地方都需要这些检查,并且您可以拥有一系列可读的代码行,因为它们不会被error handling所掩盖。

所以…建议是,你应该拥有最少的尝试/捕获量,这应该意味着大多数方法都不需要。

但是,这里有一些应该使用它们的地方:

  • 当操作失败时(写入日志文件或向用户显示错误消息),只有在您知道程序可以继续并且现在因为一个操作失败而现在不处于损坏状态时才执行此操作。 操作必须彼此隔离。
  • 在您的Main方法中记录由于它而在程序终止之前未在别处处理的任何exception。
  • 在可以采取措施的地方,例如重试操作或回退到较低的操作模式。
  • 哪里有一个糟糕的API,不允许你测试你需要处理的条件。 例如,如果要打开文件,并且API未提供DoesFileExist(),则可以先调用。

我现在无法想到其他任何地方……那是因为尝试/捕获应该很少而且很远!

当抛出任何exception时,我总是将调试器设置为中断。 它很少会中断,因为exception是例外。

我会说这取决于。 对我来说,看起来有点草率,所有这些尝试捕获到处都是。 我尝试整合到一个有许多捕获量的try块。 有时这不起作用,你可能需要将它们分开,但为了保持可读性,至少我更喜欢它。

此外,如果您的方法过长,您可以提取方法来分发您的try catch。

这取决于。 exception处理的目的就是在发生时处理运行时exception。

我通常有一个catch catch all / catch然后我在我知道有可能抛出exception(类型转换等)的代码区域周围放置try catch块。

使用多个try / catch块的优点是它可以清楚地将您正在尝试的操作与预期的exception配对。 一般来说,如果抛出它的条件是不可恢复的(除非您正在执行记录诊断的特定exception之类的操作),否则您不会捕获exception。 像这样的代码:

 try { Operation1(); } catch (MySpecificException1) { RecoverFromExpectedException1(); } try { Operation2(); } catch (MySpecificException2) { RecoverFromExpectedException2(); } 

可能有点冗长,但这是使用流量控制exception的结果。 重要的是,您可以通过查看此代码来判断第一个操作可能抛出特定exception,并且您的代码知道如何从此exception中恢复并继续执行第二个操作。 并且try / catch块除了那之外没有做任何其他事情。

我发现整合了许多行代码,每行代码都可以将自己的exception抛入一个try块中,而且很多catch都会使代码难以阅读。 仅仅通过查看代码,什么行代码抛出什么exception就不明显了。 在我看来,尝试捕获应包含尽可能少的代码; 只有可以抛出给定exception的代码。 如果您正在编写的方法包含多个尝试捕获,则应将它们各自提取到自己的方法中。

如果在方法中有多个方法调用抛出相同的exception,这就变得更加重要。 然后它们应该处于单独的try catch中,因为当您捕获exception时,通常希望将其包装在适合当前抽象的新exception中,并附带相关的错误消息。 如果在同一个try catch中有两个语句,则您将失去为不同错误提供不同错误消息的机会。

 Object operationResult; try { operationResult = remoteService.performRemoteOperation(); } catch (RemoteException ex) { throw new BusinessException("An error occured when getting ...", ex); } // use operation result