发现一个普遍的例外是不是很糟糕?
在使用FXCop分析一些遗留代码的同时,我发现在try块中捕获一般的exception错误真的很糟糕,或者您应该寻找特定的exception。 在明信片上的想法请。
显然,这是唯一真正答案是“依赖”的问题之一。
它依赖的主要是你在哪里捕捉exception。 一般来说,图书馆在捕捉exception方面应该更加保守,而在程序的顶层(例如,在主要方法或控制器的操作方法的顶端等),你可以更自由地使用你所捕获的东西。
这样做的原因是,例如你不想捕获库中的所有exception,因为你可能会掩盖与你的库无关的问题,比如你真的更喜欢“OutOfMemoryException”,这样用户可以通知等等。另一方面,如果你正在讨论捕获exception的main()方法中的exception,那么显示它然后退出……好吧,这里可能很安全地捕获任何exception。
关于捕获所有exception的最重要的规则是,你永远不应该只是无声无息地吞下所有的exception……例如Java中的这样的东西:
try { something(); } catch (Exception ex) {}
或者在Python中:
try: something() except: pass
因为这些可能是一些最难追查的问题。
一个好的经验法则是,你只应该捕捉你可以正确处理的exception。 如果你不能完全处理这个exception,那么你应该让它冒出来给可以的人。
除非你在应用程序的前端执行一些日志logging和清理代码,否则我认为捕获所有exception是不好的。
我基本的经验法则是捕捉所有你期望的exception,其他的东西都是一个错误。
如果你抓住了一切,继续下去,就像在汽车仪表板上的警示灯上贴一块石膏。 你再也看不到了,但这并不意味着一切都好。
是! (应用程序的“顶部”除外)
通过捕获一个exception并允许代码执行继续下去,你就是说你知道如何处理和规避,或者解决一个特定的问题。 你说这是一个可以回收的情况 。 捕获exception或SystemException意味着您将发现IO错误,networking错误,内存不足错误,缺less代码错误,空指针解引用等问题。 说你可以处理这些是谎言。
在组织良好的应用程序中,这些不可恢复的问题应该在堆栈中处理。
另外,随着代码的发展,你不希望你的函数捕获将来添加到被调用方法的新的exception。
在我看来,你应该捕捉你期望的所有exception,但是这个规则只适用于你的界面逻辑。 一直沿着调用堆栈,您应该创build一种方法来捕获所有exception,做一些日志logging/给予用户反馈,如果需要,可能会优雅地closures。
没有什么比应用程序崩溃,用户不友好的堆栈跟踪转储到屏幕上。 它不仅会给你的代码带来(也许是不必要的)洞察力,而且会让你的最终用户感到困惑,有时甚至会把它们吓跑到一个竞争的应用程序中去。
关于这个问题已经有了很多的哲学讨论(更像是争论)。 就我个人而言,我相信你能做的最糟糕的事情就是吞下exception。 下一个最糟糕的情况就是允许一个例外冒泡,直到用户得到一个充满技术的庞然大物的恶劣屏幕。
那么,我没有看到捕捉一般exception或特定的区别之间的区别,除了有多个catch块时,你可以作出不同的反应,取决于exception是什么。
你将捕获IOException和NullPointerExceptionexception,但是你编程的方式应该反应可能是不同的。
我认为这一点是双重的。
首先,如果你不知道发生了什么exception,你希望如何从中恢复。 如果你期望用户可能input错误的文件名,那么你可以期待FileNotFoundException,并告诉用户再次尝试。 如果这个相同的代码产生了一个NullReferenceException,你只是告诉用户再试一次,他们不知道发生了什么。
其次,FxCop准则的重点是图书馆/框架代码 – 并不是所有的规则都适用于EXE或ASP.Net网站。 所以有一个全球性的exception处理程序,将logging所有exception并很好地退出应用程序是一件好事。
捕捉所有例外的问题是,你可能正在捕捉那些你不期望的东西,或者那些你不应该捕捉的东西。 事实上,任何types的exception都表示出了什么问题,而且在继续之前,您必须将其排除,否则可能会导致数据完整性问题以及其他不容易追查的错误。
举一个例子,在一个项目中,我实现了一个名为CriticalException的exceptiontypes。 这表示需要开发人员和/或pipe理人员干预的错误情况,否则客户得到不正确的计费,或者可能导致其他数据完整性问题。 也可以用于其他类似情况,仅仅loggingexception情况是不够的,需要发送电子邮件提醒。
另一个没有正确理解exception概念的开发人员则将一些可能会抛出exception的代码封装在一个通用的try … catch块中,这个块抛弃了所有的exception。 幸运的是,我发现了这个问题,但是这可能会导致严重的问题,特别是因为本来应该捕获的“非常罕见”的情况比我预想的要普遍得多。
所以一般来说,捕获genericsexception是很糟糕的,除非你100%确定你确切地知道哪些types的exception将被抛出以及在哪些情况下。 如果有疑问,让他们冒泡到顶层exception处理程序。
类似的规则在这里不会抛出System.Exceptiontypes的exception。 您(或其他开发人员)可能希望在调用堆栈的上方捕获您的特定exception,同时让其他人通过。
(有一点需要注意,在.NET 2.0中,如果一个线程遇到任何未捕获的exception,它将卸载你的整个应用程序域,所以你应该把一个线程的主体包装在一个通用的try … catch块中,任何exception都会被捕获到您的全局exception处理代码中。)
大部分时间捕捉一般的exception是不需要的。 当然,有些情况下你没有select,但在这种情况下,我认为最好是检查一下为什么你需要抓住它。 也许你的devise有问题。
我想扮演魔鬼的追随者,抓住exception并logging下来,然后重新抛出它。 这可能是必要的,例如,如果你在代码的某个地方,发生意外的exception,你可以捕获它,logging有意义的状态信息,这些信息在一个简单的堆栈跟踪中是不可用的,然后将它重新推送到上层处理。
我认为一个很好的指导方针是只捕获框架内的特定exception(以便主机应用程序可以处理边缘情况,如磁盘填满等),但我不明白为什么我们不应该能够捕捉所有我们的应用程序代码的例外 很简单,有些时候你不希望应用程序崩溃,不pipe出什么问题。
一般的例外情况,我感觉就像是在燃烧的build筑物里面拿着一根炸药棒,放出引信。 它有助于一段时间,但一段时间后,炸药会反弹。
可能有些情况下需要捕获一个普通的exception,但仅用于debugging目的。 错误和错误应该是固定的,而不是隐藏的。
- 无法加载文件或程序集System.Net.Http.Primitives。 位于程序集的清单定义与程序集引用不匹配
- 在服务器上打开IncludeExceptionDetailInFaults(来自ServiceBehaviorAttribute或来自<serviceDebug>configuration行为)
- 抛出一个NotImplementedError在PHP中?
- “EXC_BREAKPOINT(SIGTRAP)”由debugging断点引起的exception吗?
- 我怎样才能testing预期exception与Visual Studiotesting中的资源文件中的特定exception消息?