【问题标题】:Wouldn’t handling an exception be a better idea处理异常不是一个更好的主意
【发布时间】:2010-09-19 18:33:11
【问题描述】:

1)

1 - 仅处理您认为的异常 实际上可以做点什么,
2 - 你对绝大多数异常无能为力

a) 我假设 “By not handling an exception” 的文字建议我们应该让异常冒泡到堆栈中,运行时将在哪里中止我们的应用程序?!

b) 但是为什么让运行时中止异常而不是捕获异常、记录它然后通知用户失败?两者之间的唯一区别是在后一种情况下应用程序不会中止

例如,如果数据库出现故障,为什么整个程序会崩溃(由于没有处理异常),如果我们可以捕获异常,记录并通知用户失败,这样我们就可以保持程序正常运行并运行

2) 如果您知道某些代码块可能引发的异常无法处理,您应该将此代码包含在 try-finally 块中还是将其留在任何 try-finally 块之外更好?

谢谢

【问题讨论】:

  • 我不知道引号的完整上下文。但我认为正确的解释是:(A)如果你是一个class设计师,那么就遵循这些规则。基本上,不要隐藏意外的异常。 (B) 但如果您是应用程序 开发人员,那么这些规则不适用于您;如果你能帮助它,不要让你的程序崩溃。

标签: c# exception-handling


【解决方案1】:

不,准则是不要捕获您无法对除了在您的应用程序或线程的顶级之外做任何事情的异常。

您应该尽量避免让您的应用程序崩溃 - 将信息记录在某处,向您的用户发送一条消息,解释发生了什么,并告诉他们如何向您报告错误。也许还可以尝试将他们未保存的数据保存在恢复文件中,以便下次启动应用程序时,它可以提供尝试恢复他们丢失的工作的选项。

【讨论】:

  • 我同意。如果它是最终用户应用程序,则在顶层捕获它、记录它并向用户显示一个合理的对话框。
【解决方案2】:

尝试以这种方式查看它...数据库出现故障。你怎么知道的?因为你得到一个超时/一个异常/东西。但是您的应用程序可能没有得到异常。 ADO.NET/Linq 到 SQL/Entity Framework/您使用的任何数据提供程序实际上都是在获取异常并将其抛出到您的应用程序。对我来说,这就是该建议所建议的:作为组件设计师,更愿意抛出你无能为力的异常。

对于数据库关闭示例,ADO.NET 数据提供程序可以做什么?它可以使服务器备份吗?修复网络连接?重置权限?不,所以它不处理异常,而是抛出异常。

您引用的指南是针对组件开发的,而不是运行时边界(线程或应用程序)的外边缘。在那个级别上,决定如何处理冒泡到现在的异常是正确的。

【讨论】:

    【解决方案3】:

    我认为您引用的人建议您应该让异常在堆栈中冒泡直到更高的东西可以理解它直到它到达调用堆栈的顶部 你确实有代码可以记录它,或者向用户显示错误消息,如果它是致命的,则退出你的程序,如果不是,则继续。

    有时最好不要继续执行程序 - 例如,如果您收到 OutOfMemoryException 或程序操作未定义的其他情况 - 潜在的灾难。

    【讨论】:

      【解决方案4】:

      我认为关键

      仅处理您可以实际处理的异常

      只有当您可以在您的应用程序中从该点继续时,您才应该处理异常。

      举个小例子。

      如果您正在用户系统上查找文件,但该文件不存在,您应该引发“找不到文件”异常。现在,如果您可以从中恢复(例如通过简单地重新创建文件),那么就这样做并继续。但是,如果无法重新创建文件,那么您不应该让您的程序继续运行。

      但是,这并不意味着您不能在主程序中使用顶级捕获所有异常处理程序来向用户显示友好的消息,也许可以记录异常,甚至将其邮寄给开发人员。

      【讨论】:

        【解决方案5】:

        这句话是正确的。但它是在更深层次的应用程序中捕获异常的参考。基本上我们写的大部分代码都不需要异常处理。只有应用程序的客户端部分负责捕获错误并将其呈现给用户 - 以及日志记录。

        例如,相同的业务代码/数据库代码可以在 Web 应用程序和 windows/wpf 应用程序中使用,并且日志记录/处理可能不同,并且更深层不知道如何处理,因此他们需要 将责任留给 UI 层

        【讨论】:

        • “只有应用程序的客户端部分负责捕获错误......”客户端部分是指类似于 Asp.net 应用程序的东西?
        【解决方案6】:

        关键是您不希望在代码的任何地方都嵌套 try/catch 块,因为这往往会隐藏代码的问题。最好仅在您了解错误和所需结果的情况下实施异常处理,否则不要处理它并让它冒泡。

        至于冒泡的错误,您应该为这些未捕获的应用程序错误提供一个全局异常处理程序。这仅在您的应用程序中的一个位置实现,并允许您记录错误或向用户显示错误。同样,这仅在您的应用中的一个位置实现,并通过挂钩 application.error 事件来实现。

        在 .net win 表单应用程序中挂钩的事件:

        AppDomain.CurrentDomain.UnhandledException
        

        在 .net asp.net 应用程序中挂钩的事件:

        HttpApplication.Error
        

        享受吧!

        【讨论】:

          【解决方案7】:

          在不了解这两个语句的上下文的情况下,声明两个语句都适用于方法和类,那么它们是有意义的:

          调用方法的一段代码只能处理它有足够的上下文信息的异常。在大多数情况下,一段代码没有足够的信息来处理所有异常。

          示例:一段代码调用SaveData() 方法可以在知道将数据保存到数据库时处理DatabaseStorageException。另一方面,如果这段代码是以与存储无关的方式编程的,那么捕获这样一个特定的异常并不是一个好主意。这种情况下最好让异常弹出调用栈,让其他代码处理异常,有足够的上下文信息来处理。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-04-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-12
            • 1970-01-01
            相关资源
            最近更新 更多