什么"只捕捉你可以处理的例外"真的意味着什么?

Kyl*_*Lib 12 c# exception-handling

我的任务是编写一个我正在研究的.NET/C#项目的异常处理策略和指南文档.我很难接受它.有很多关于如何/何时抛出,捕获,包装异常的信息,但我正在寻找描述catch块内部应该进行哪些事情,而不是包装和抛出异常.

try
{
   DoSomethingNotNice();
}
catch (ExceptionICanHandle ex)
{
   //Looking for examples of what people are doing in catch blocks
   //other than throw or wrapping the exception, and throwing.
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

Kei*_*thS 13

这意味着什么.如果您期望正在运行的代码抛出异常,并且当抛出该异常时您的代码知道出了什么问题以及如何继续,那么捕获异常并处理它.

基本上,规则存在以防止反模式,如:

try
{
   ...
}
catch(Exception ex)
{
   throw;
}
Run Code Online (Sandbox Code Playgroud)

这里的捕获只会添加一个减速带来解除调用堆栈.如果你真的不希望任何事情,你抓住的例外,你甚至不应该打扰捕获.

一个相关但更有效的案例是你不关心被抛出的异常,但是你需要在所有情况下进行清理.在这种情况下,跳过捕获; 你不需要它,只需将它作为try-finally块.

编辑:要回答帖子中的问题,而不仅仅是主题,您可以编写如下规则:"不要编写不执行任何操作的try-catch语句,或者只重新捕获捕获的异常.所有catch语句都应该执行一些与抛出的例外有关的增值行动."

例如,假设您尝试使用用户在登录应用程序时提供的凭据连接到SQL Server实例.许多事情可能会出错,其中一些你不能指望,其中一些你应该.

  • 服务器没有响应 - 你可以再试一次; 也许在catch中递归调用连接方法,使用"重试计数器"来打破无限循环.
  • 用户身份验证失败 - 在对话框中显示红色的友好(或不那么友好,但简洁易懂)消息.
  • 用户无权连接到指定的数据库 - 取决于您的安全设置; 在大多数办公室,你应该通过电子邮件向DBA发送电子邮件,因为这意味着他创建了登录但忘记分配适当的权限.
  • 网络不可用:您可以通过登录对话框或新对话框中的错误提醒用户,重试几次等.
  • 除以零 - WTF?在登录期间可能导致Div by Zero的原因是什么?你不期待这个例外,你不知道在这种情况下出了什么问题因此无法继续运行代码,所以不要抓住它.
  • 如果出现任何问题,您可能希望将消息记录到文件或共享资源以用于审计/安全目的.如果你想继续执行,这应该发生在较低级别,如果你以后要优雅地关闭,则应该发生更高级别.

所有这些示例都涉及首先捕获已知类型的异常并询问它以查看确切的错误,然后执行一些可以允许程序继续执行的已知操作.目的是防止应用程序在出现错误时崩溃和刻录,以防止您知道可能出错,但知道在这种情况下如何保持程序运行.

捕获异常的基本规则:

  1. 如果您没有预料到异常,请不要抓一个.
  2. 如果您在收到异常后不能或不想继续执行代码,无论您是否知道它可能发生,都不要抓住它.
  3. 如果您希望发生异常,并知道如何在代码发生时继续执行代码(至少暂时),则捕获并执行您需要的任何特殊操作.
  4. 永远不会捕获异常(一个空的捕获块); 这导致应用程序以更加不可预测的方式无声地失败.
  5. 永远不要在生产代码中留下catch-and-rethrow(只有一个重新抛出的catch块).它们有时在调试时很有用,因为它们允许您识别失败的特定代码段,但在生产代码中,它们只是甩掉或实际处理异常的速度.