我在这里阅读了几篇关于异常处理/重新抛出异常的帖子(通过查看最高投票线程),但我有点困惑:
- 为什么你不希望直接catch块处理异常,而是在它之上呢?
- 另外,我经常读到你应该只处理你可以“处理”的异常。这是否意味着实际做了些什么,比如重试操作?
答案 0 :(得分:3)
您可能希望捕获异常(例如,找不到文件)并进行一些处理 - 例如如果你打开了两个文件并且缺少第二个文件,你将需要在继续之前再次关闭第一个文件,这样它就不会打开。
然后,您可能希望告诉调用者发生了错误,因此您重新抛出相同的异常或抛出一个新异常,描述问题。
在某些情况下,如果您遇到异常,您的代码无法知道它是否是错误(例如,如果要求您加载XML文件,但是您收到了File Not Found异常,那就是错误,还是应该返回空白的XMl结果?)。在这些情况下,您要么重新抛出异常,要么不处理所有异常,并让调用代码决定如何处理该问题。
答案 1 :(得分:1)
你的第二点是对第一点的回答。有时,较低级别的功能对应用程序的上下文了解不足以了解正确的操作应该是什么。例如,如果打开文件以进行读取失败,因为没有该名称的文件,则应用程序可能想要请求不同的文件,或者中止整个操作,或者其他任何操作。在某种程度上,应用程序的某些部分将负责做正确的事情,除非当然只是程序崩溃是可接受的行动。
答案 2 :(得分:0)
回答你的第二个问题 - 只有在可以对它做任何事情时才需要在立即块中处理异常:例如关闭与db的连接,关闭流,重试或使用不同的params重试,记录异常(如果有的话)不是更高级别的异常通用处理程序)。可能只有直接的代码块知道这些细节并且可以处理它们。调用块需要知道发生错误,他们可能更好地知道如何处理异常。
例如,立即块可以处理文件。调用者可能会尝试从不同位置打开文件(在“探测”过程中)并忽略多个错误,只要至少有一个成功。代码的另一部分可能会将第一次失败的尝试视为错误。调用者块可能会选择通知用户发生了错误,可能让他/她知道一些有关如何解决问题的有用信息。此外,提供通知支持问题的方法也很好 - 某种对话框允许用户寻求帮助,描述问题并发送消息。在此消息中,您可以附加日志,有关环境的一些信息,如操作系统,框架版本,程序,浏览器功能,无论您需要诊断问题(如果用户允许您这样做)。
答案 3 :(得分:0)
如果捕获它的方法可以满足其构造,则“处理”异常。例如,当用户从“最近文件”菜单中选择项目时调用的例程OpenRecentDocument
的合同可能指定它必须(1)成功打开文档窗口,或(2)尝试失败打开文档窗口,回滚尝试产生的任何副作用,并通知用户发生了什么。如果OpenRecentDocument
在尝试打开文件时捕获异常,但它能够回滚尝试中的任何副作用并通知用户,则例程将满足其合同,因此应该返回而不重新抛出异常。
所有这一点中的一个不幸的“陷阱”是,没有任何标准方法可以通过这些方法抛出异常的例程可以指示他们的尝试操作是否导致无法回滚的副作用。例如,没有固有的方法来区分在更新共享数据结构时意外发生的InvalidOperationException
(这意味着其他打开的文档可能已被破坏),从InvalidOperationException
发生的同时更新与正在加载的文档相关联的数据,即使已经预见到后者的可能性并为其提供。最好的方法是尝试捕获在后一种情况下可能发生的任何InvalidOperationException
,它将该异常封装在其他异常类型中,然后抛出它,或者让数据结构保持一个“object corrupted”标志并确保如果发现数据结构已损坏,则其上的所有未来操作都将尽可能干净地失败。这两种方法都不优雅。更常见的方法,可能被描述为“最好的希望”,通常是有效的。