我一直听到这个
catch (Exception ex)
然而,不好的做法是,我经常在事件处理程序中使用它,例如,操作可能会进入网络,从而可能出现许多不同类型的故障.在这种情况下,我捕获所有异常并在消息框中向用户显示错误消息.
这被认为是不好的做法吗?除了异常之外我无能为力:我不希望它停止应用程序,用户需要知道发生了什么,而且我处于代码的顶层.我还应该做什么?
编辑:
人们说我应该查看调用堆栈并专门处理错误,因为例如StackOverflow异常无法有意义地处理.然而,停止这个过程是最糟糕的结果,我想不惜一切代价阻止这一过程.如果我无法处理StackOverflow,那么就是这样 - 结果将不会比没有捕获异常更糟糕,并且在99%的情况下,就我而言,通知用户是最不好的选择.
此外,尽管我尽最大努力解决可能引发的所有可能异常,但在大型代码库中,我可能会错过一些.对于他们中的大多数人来说,最好的防御仍然是告知用户.
不好的做法是
catch (Exception ex){}
和变种:
catch (Exception ex){ return false; }
等等
捕获顶层的所有异常并将它们传递给用户(通过记录它们或在消息框中显示它们,具体取决于您是在编写服务器还是客户端应用程序),这是正确的做法去做.
我发现泛型捕获总是不好过分教条的论点.他们和其他一切一样,都有一席之地.
那个地方不是您的图书馆代码,也不是您为自己的应用程序定制开发的课程.正如许多人所提到的,这个地方是应用程序的最高级别,如果引发任何异常,则很可能是意外的.
这是我的一般规则(和所有规则一样,它的设计在适当的时候被破坏):
我在应用程序中使用类和自定义构建的库来完成大部分工作.这是基本的应用程序架构 - 非常基本,请注意.这些人尝试尽可能多地处理异常,如果他们真的无法继续,请将最具体的类型提供给UI.
在UI中,我倾向于始终从事件处理程序中捕获所有内容.如果有合理的期望捕获特定的例外,并且我可以做一些事情,然后我抓住了特定的异常并优雅地处理它.但是,这必须在catch all之前,因为.NET将只使用与您的异常匹配的第一个异常处理程序.(总是从最具体到最通用的订购!)
如果我不能对异常做任何事情而不是错误输出(例如,数据库处于脱机状态),或者异常确实是意外的,那么catch all将接受它,记录它并快速失败,并带有一般错误消息在临终前显示给用户.(当然,某些类型的错误几乎总是会失败 - OutOfMemory,StackOverflow等等.我很幸运,没有必要处理prod级代码中的那些......到目前为止!)
抓住一切都有它的位置.那个地方不是为了隐藏异常,那个地方不是为了尝试和恢复(因为如果你不知道你抓到了什么,你怎么可能恢复),那个地方不是为了防止错误显示给用户同时允许你的应用程序继续在未知和糟糕的状态下执行.
抓住所有的地方是最后的手段,一个陷阱,以确保如果有任何东西通过你精心设计和保护良好的防御,至少它被适当记录,并可以做出干净的退出.它是坏的做法,如果你没有精心设计和较低级别戒备森严的地方部队,这是非常低级别的做法不好,但作为最后的手段是做(在我心中)不仅是可以接受,但往往是正确的事情.
当我看见
catch (Exception ex)
我的手开始摸索着锤子.几乎没有任何借口可以捕获基础异常.只有我认为有效的案例是:
1)第三方组件抛出异常(该死的作者)
2)非常顶级的异常处理(作为最后的手段)(例如处理WinForms应用程序中的"未处理"异常)
如果您发现可能发生许多不同类型的异常的情况,那么这是设计糟糕的好兆头.
我不同意Armin Ronacher.如果引发StackOverflow异常,您会如何表现?尝试执行其他操作可能会导致更糟糕的后果.仅在您能够以有意义且安全的方式处理异常时才捕获异常.捕获System.Exception以涵盖可能的异常范围是非常错误的.即使你重新投掷它.
在代码中的最高级别捕获异常是完全合理的.捕获基础异常类型很好,只要您不需要根据异常类型执行任何不同的逻辑.
此外,请确保您显示友好的常规错误消息,而不是显示实际的异常消息.这可能会导致安全漏洞.