【问题标题】:How to catch a specific exception if the possible list of exceptions are too many?如果可能的异常列表太多,如何捕获特定异常?
【发布时间】:2016-03-06 15:22:06
【问题描述】:

我有这段代码试图将一些信息保存到文件中

try
{
    foreach (var str in strlist)
    {
        var jsonData = str;
        File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory)+"test\"+".json",jsonData.ToString());
        savedFiles++;
    }
}
catch (Exception exception)
{
    _log.ErrorFormat("Exception occurred in Saving JsonDocs , exception Message {0}", exception.Message);
    return savedFiles;

}

当我签入这段代码时,我的 SONAR 开始抱怨我应该捕获特定异常

但我这里唯一的逻辑是 文件 保存,它可以有以下所有可能的例外情况

那么如果一个 File 操作可以抛出 8 种类型的异常,我该如何捕捉特定的异常呢?这是否意味着我必须编写多个 catch 块?

【问题讨论】:

  • 首先弄清楚category每个可能的异常在什么位置。例如,ArgumentException - 你不应该抓住一个,因为你不应该将错误的参数传递给函数第一名。
  • 都派生自 SystemException。如果你抓住它怎么办?如果没问题,您也应该在日志文件中包含异常的类型,使用 exception.GetType()。我还观察到您只保留已保存文件的计数,而不是每个文件的状态。您应该真正考虑跟踪每个文件的保存操作状态,而不仅仅是成功保存的计数。

标签: c# .net exception-handling sonarqube


【解决方案1】:

所以如果一个文件操作可以抛出 8 种类型的异常,我该怎么办? 捕获一个特定的异常?这是否意味着我必须写多个 抓块?

是的,您需要为要捕获的每个异常编写特定的catch 子句,从特定的到一般的。

The documentation on try-catch is pretty clear:

可以在同一个文件中使用多个特定的 catch 子句 try-catch 语句。在这种情况下,catch 子句的顺序是 很重要,因为 catch 子句是按顺序检查的。赶上 在不太具体的例外之前有更具体的例外。编译器 如果您订购 catch 块以便稍后的块产生错误 永远无法到达。

try
{
    foreach (var str in strlist)
    {
        var jsonData = str;
        File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory)+
                          "test\"+".json", jsonData.ToString());
        savedFiles++;
    }
}
catch (PathTooLongException pe)
{
    // Do Stuff
}
catch (Exception exception)
{
    _log.ErrorFormat("Exception occurred in Saving JsonDocs , 
                      exception Message {0}", exception.Message);
    return savedFiles;
}

意味着如果PathTooLongException 被抛出,它将被那个catch 子句捕获。如果您错误地切换了 catch 子句的顺序,并且首先使用了 Exception,它将优先于任何其他异常处理子句。

【讨论】:

  • 谢谢,所以如果有任何方法可以“N”个异常,我应该写“N”个捕获块。这样会导致方法太大,还要写'N'个单元测试用例?
  • @CSharped 没有一般准则,但通常是的。抛出这么多异常的方法并不常见。例如,ArgumentExceptionArgumentNullException 不是您真正想要“处理”的异常,您只是想修复调用代码。更何况,大多数时候你会想要对你的异常做一些更一般的事情,比如日志。
【解决方案2】:

简而言之,是的。您需要捕获并处理每种异常类型。

但是,ArgumentNullException 继承自 ArgumentException。另外,PathTooLongExceptionDirectoryNotFoundException 都是 IOExceptions。

因此,实际上,您将需要处理 5 种异常类型,而不是 8 种。

【讨论】:

  • 谢谢,如果我有一个针对特定异常的 catch 块,而没有针对一般异常的 catch 块,会发生什么。但是发生的异常是不同类型的
【解决方案3】:

在给定的示例中,我将为 IO 异常添加 catch 块,因为这些是由于真正的 IO 问题而在运行时真正发生的异常。所有其他异常只能针对您无论如何都无法处理的严重问题或周围代码中的错误抛出。例如,您的列表中可能有一个null 字符串导致ArgumentException

在后一种情况下,您的应用程序有问题,它应该崩溃而不是继续它在未指定的状态下工作。

【讨论】:

    猜你喜欢
    • 2016-07-09
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 2012-11-11
    • 2010-12-31
    • 1970-01-01
    相关资源
    最近更新 更多