忽略异常

Ignoring exceptions

提问人:stimms 提问时间:10/24/2008 更新时间:6/2/2009 访问量:853

问:

我有一些代码忽略了特定的异常。

try
{
    foreach (FileInfo fi in di.GetFiles())
    {
        collection.Add(fi.Name);
    }
    foreach (DirectoryInfo d in di.GetDirectories())
    {
        populateItems(collection, d);
    }
}
catch (UnauthorizedAccessException ex)
{
   //ignore and move onto next directory
}

当然,这会导致编译时警告,因为 ex 未使用。是否有一些标准的接受noop应该用于删除此警告?

C# 异常

评论


答:

12赞 tvanfosson 10/24/2008 #1

只需将其重写为

catch (UnauthorizedAccessException) {}

评论

1赞 Jon Skeet 10/24/2008
但请仍然包括评论!生产代码中只有一个完全空的块不应该通过 IMO 的代码审查。
0赞 Joe 10/24/2008
>“但请仍然包括评论,,,”。不同意这一点。“catch(SomeException) {}” 已经清楚地表明“忽略 SomeException”,在许多情况下,额外的注释将是多余的。
1赞 Booji Boy 10/24/2008 #2

我通常这样做

Debug.WriteLine(ex.message)

(这样,如果需要,我也可以在异常中设置断点)

2赞 Scott Dorman 10/24/2008 #3

正如 Dave M. 和 tvanfosson 所说,你想把它改写为

catch (UnauthorizedAccessException) {}

然而,应该问的更大的问题是,为什么你在忽略它时会发现一个异常(通常称为吞下异常)?这通常是一个坏主意,因为它可以(并且通常确实)在运行时隐藏应用程序中的问题,这可能会导致非常奇怪的结果并且很难调试它们。

评论

0赞 MusiGenesis 10/24/2008
至少它比“catch(Exception) {}”要好。
0赞 Scott Dorman 10/24/2008
没错,但只是稍微好一点。
0赞 Jon Skeet 10/24/2008
我认为有时可以发现一个例外并吞下它,但应该始终有一个评论来解释你为什么要这样做。
0赞 Joe 10/24/2008
捕获这样的特定异常是完全可以的。
0赞 Robert Rossney 10/24/2008
同意。特别是因为用于检查目录访问权限的代码非常重要。
-1赞 Alan 10/24/2008 #4

尽管我是 Java 开发人员(不是 C#),但 @Scott Dorman 是绝对正确的。你为什么要“吞下例外”?更好的是,什么引发 UnauthorizedAccessException?以下是常识性的可能性:

  1. 文件不存在
  2. 目录不存在
  3. 当前控制线程没有正确的安全权限。在 *nix 世界中,当前线程可能位于错误的组或错误的用户中。
  4. 磁盘崩溃
  5. 文件的 ACL 设置为仅写入,但不写入。同样,对于目录。

当然,以上是一个不完整的列表。

评论

0赞 Robert Rossney 10/26/2008
其中三种常识性可能性不会引发 UnauthorizedAccessException。另外两个正是该方法吞下异常的原因:它只想要它有权访问的文件。
1赞 Robert Rossney 10/24/2008 #5

假设原始代码中的注释是对您尝试执行的操作的准确描述,我认为您想这样编写:

foreach (FileInfo fi in di.GetFiles())
{
    //TODO:  what exceptions should be handled here?
    collection.Add(fi.Name);
}

// populate collection for each directory we have authorized access to
foreach (DirectoryInfo d in di.GetDirectories())
{
    try
    {
        populateItems(collection, d);
    }
    catch (UnauthorizedAccessException)
    {
        //ignore and move onto next directory
    }
}

然后你需要处理那个待办事项。

评论

0赞 Joe 10/24/2008
TODO 项很简单 - 几乎可以肯定您不想在那里处理任何异常。
0赞 Robert Rossney 10/26/2008
你可能是对的。但是我不会假设知道原始发布者打算用代码做什么,在代码审查中,我会让他告诉我。
1赞 Matthew 6/2/2009 #6

我同意那些说简单地忽略例外可能是一个坏主意的人。如果你不打算重新扔掉它,那么至少把它记录在某个地方。我编写了一些小工具来处理文件列表,在这些文件中,我不希望单个文件的错误导致整个程序崩溃,在这种情况下,我会打印一条警告消息,以便我可以看到哪些文件被跳过了。

我个人唯一一次在没有命名的情况下捕获异常,例如在 catch(xxxException) 中,如果我要以某种方式对它做出反应,然后重新抛出它,以便我可以在某个外部例程中捕获它。例如:

try
{
    // do something
    // ...
}
catch(UnauthorizedAccessException)
{
    // react to this exception in some way
    // ...

    // let _someone_ know the exception happened
    throw;
}