2

据我所知,您应该只在实际处理异常时才使用 try/catch,而不仅仅是报告和记录它然后使应用程序崩溃。否则,您最好只检查有意义的不同场景(例如,如果 sth==null)或者 - 如果您的目的只是记录异常并使应用程序崩溃 - 使用AppDomain.UnhandledException。但情况总是如此,为什么?

假设以下方法,它接受一个数组并在执行一些数据库和文件系统操作后返回 MemoryStream。

MemoryStream Read (int[] IDs)
{
    try
    {
        using (SqlConnection connection = new SqlConnection(connection_string))
        {
            connection.Open();    

                        // a bunch of code executing SQL queries & constructing MemoryStream, which is returned at the end of the block
        }
    }
    catch (Exception e)
    {
        // report the exception to the user & log it
        throw; // pointles??                
    }
}

有多种情况可以被视为异常/不需要的行为,例如:

  • 参数 (IDs[]) 为空,
  • 无法建立 SQL 连接,
  • 无法执行特定的 SQL 查询。

所有这些情况都被认为是异常的,如果您只想记录异常(然后崩溃),仍然将所有内容放在 try/catch 中可能是不好的做法 - 但为什么呢?在上述情况下,最佳处理行为是什么?完全避免 try/catch,使用 if 语句检查 null 引用(在这种情况下返回 null)并使用 AppDomain.UnhandledException 记录其他所有内容?使用 try/catch,但仍然使用 if 语句检查空引用(并在这种情况下返回)?还有什么?

4

3 回答 3

2

使用 try/catch 语句来添加代码只是为了让应用程序崩溃是没有效率的。CLR 已经为您解决了这个问题。并且您有 AppDomain.UnhandledException 来生成体面的信息来诊断原因。

只有在非常特殊的情况下,你必须清理一些东西,比如一个你不想继续放置的文件,你是否应该考虑编写一个 try/catch。这本身就是一个非常不确定的要求,无法保证您的 catch 块将执行。当异常像 StackOverflowException 或 ExecutionEngineException 这样令人讨厌时,它不会。或者程序不自行清理的更常见原因,有人绊倒电源线或从任务管理器中终止进程。

于 2013-01-31T14:47:59.480 回答
1

您应该仅在实际处理异常时才使用 try/catch,而不仅仅是报告和记录它然后使应用程序崩溃

我同意第一部分,尽管我要补充一点,当您可能无法控制调用层时,在层边界添加日志记录是有价值的。例如,我在顶部方法中记录 Web 服务中发生的所有异常,以确保我已登录服务器,因为调试信息(堆栈跟踪等)并不总是优雅地跨通信层

在您的特定示例中,我将检查“异常”条件,您可以但让其他异常“自然”发生。对于您的具体示例:

  • 参数 (IDs[]) 为空,
  • 无法建立 SQL 连接,
  • 无法执行特定的 SQL 查询。

null对于第一个,我会出于一个原因检查参数:A没有NullReferenceException为您提供有关异常原因的上下文,除了它发生的位置。我更喜欢检查然后抛出一个新异常,因为您可以添加哪个参数为空。您可能仍需要进行一些挖掘以找出它为空的原因,但它可以为您节省大量调试时间。nullArgumentNullException

SQL 异常通常可以自然地冒泡,因为它们中有不错的错误信息(例如"undeclared variable '@arg'"

于 2013-01-31T15:06:30.857 回答
1

我最近开始自己阅读这个主题。我的基本理解是:

  1. 仅当您打算处理异常时才捕获异常。
  2. 过度使用 try/catch 会导致异常吞噬和/或丢失有价值的堆栈跟踪信息,并可能导致可维护性问题(如果您决定将错误/日志标准化怎么办?)。而是使用 try/finally 或使用块来实现清理。
  3. 通过全局异常处理程序在边界处捕获异常。
  4. 顾名思义,使用 AppDomain.UnhandledException:记录未处理的异常。如果你不记录这些,你只会在日志查看器中找到一个 CLR“Windows 错误报告”条目和一些对你真的没用的转储文件。使用 AppDomain.UnhandledException 总是一个好主意,所以如果您的应用程序确实崩溃了,您就会知道原因。

需要注意的是,“处理”异常并不一定意味着清理或追溯逻辑。处理可能只是意味着将错误格式化为对用户更友好的内容,或者隐藏您不希望任何人看到的敏感堆栈跟踪。我通常会记录一个详细的错误并返回一个格式化的错误。

同样,这正是我最初收集到的。以下是一些来源:

良好的异常管理经验法则

理解和使用异常

于 2013-01-31T15:07:57.347 回答