在使用 FXCop 分析一些遗留代码时,我突然想到,在 try 块中捕获通用的异常错误真的那么糟糕吗?还是应该寻找特定的异常类型呢?请您来分享一下您的想法。
在使用 FXCop 分析一些遗留代码时,我突然想到,在 try 块中捕获通用的异常错误真的那么糟糕吗?还是应该寻找特定的异常类型呢?请您来分享一下您的想法。
显然,这是那种唯一真正答案是“取决于情况”的问题之一。
它主要取决于你捕获异常的位置。通常来说,库应该更加保守地捕获异常,而在程序的顶层(例如在主方法中或者控制器的操作方法的顶部等),你可以更加自由地捕获异常。
原因是,例如,你不希望在库中捕获所有异常,因为你可能会掩盖与你的库无关的问题,比如"OutOfMemoryException",你真的希望这些问题能够上浮以便用户得到通知。另一方面,如果你是在main()方法中捕获异常并将其显示然后退出... 那么,在这里捕获几乎任何异常都是安全的。
关于捕获所有异常的最重要的规则是,你永远不应该悄悄地吞噬所有异常... 例如在Java中这样做:
try {
something();
} catch (Exception ex) {}
或者在Python中这样写:
try:
something()
except:
pass
因为这些问题可能是最难追踪的。
一个好的经验法则是,你只应该捕获那些你自己能够正确处理的异常。如果你不能完全处理异常,那么你应该让它冒泡到能够处理的人手中。
OutOfMemoryException
。 - jrh除非您在应用程序的前端进行一些日志记录和清理代码,否则我认为捕获所有异常是不好的。
我的基本经验法则是捕获您预期的所有异常,其他任何异常都是错误。
如果你捕获了所有异常并继续执行,就像在汽车仪表板上贴一个黏性带盖住警告灯一样。虽然您看不见灯了,但这并不意味着一切都没问题。
是的!(除非在您的应用程序的“顶部”)
通过捕获异常并允许代码继续执行,您表明您知道如何处理和规避或修复特定问题。您声明这是可恢复的情况。捕获 Exception 或 SystemException 意味着您将捕获诸如 IO 错误、网络错误、内存不足错误、缺少代码错误、空指针取消引用等问题。说您能够处理这些问题是虚假的。
在良好组织的应用程序中,应该高层处理这些不可恢复的问题。
此外,随着代码的发展,您不希望您的函数捕获调用方法中未来添加的新异常。
我的观点是,你应该捕获所有你预期的异常,但这个规则仅适用于除了接口逻辑以外的所有内容。在整个调用堆栈中,你可能需要创建一种方式来捕获所有异常,进行一些记录/向用户反馈,并且如果需要和可能的话,优雅地关闭。
没有比应用程序崩溃并在屏幕上抛出一些对用户不友好的堆栈跟踪更糟糕的了。它不仅会提供(也许不想要的)代码洞察力,而且还会使最终用户感到困惑,有时甚至会吓跑他们去竞争对手的应用程序。
关于这个问题,有很多哲学性的讨论(更像是争吵)。就我个人而言,我认为最糟糕的事情是吞掉异常。其次最糟糕的是允许异常冒泡到用户面前,给用户展示一大堆让人摸不着头脑的技术术语。
嗯,我不认为捕获一般异常和特定异常之间有任何区别,除非在有多个catch块时,您可以根据异常的类型做出不同的反应。
总之,使用通用的Exception
会捕获IOException
和NullPointerException
,但您的程序应该以不同的方式做出反应。
我认为这一点有两个方面的含义。
首先,如果您不知道发生了什么异常,那么您如何希望从中恢复过来呢?如果您预期用户可能会输入错误的文件名,那么您可以预计会出现FileNotFoundException并告诉用户再试一次。但是,如果同一段代码生成了NullReferenceException,并且您只告诉用户再试一次,他们就不知道发生了什么。
其次,FxCop准则确实专注于库/框架代码-它们的所有规则都不适用于exe或ASP.Net网站。因此,拥有一个全局异常处理程序,可以记录所有异常并优雅地退出应用程序,这是一个好方法。
我想就捕获异常、记录并重新抛出它这件事提出反对意见。如果在代码中发生了意外的异常,你可以捕获它,并记录简单堆栈跟踪无法提供的有意义的状态信息,然后将其重新抛到上层进行处理,这时就会变得必要。