我的方法应该抛出自己的异常,还是让.NET抛出文件不存在?

fhn*_*eer 75 c# exception

这是我的代码:

public void ReadSomeFile(string filePath)
{
    if (!File.Exists(filePath))
        throw new FileNotFoundException();

    var stream = new FileStream(filePath, ....)
    .....
}
Run Code Online (Sandbox Code Playgroud)

我应该自己抛出异常(见File.Exists支票)吗?如果文件不存在,FileStream则会抛出FileNotFoundException.这里有什么好的编程习惯?代码分析说我们应该验证我们的参数.但是如果我将该参数直接传递给另一个方法(我的或其他代码)并且该方法本身会抛出异常,那么在我的代码中验证参数的优点是什么?

Cod*_*ter 118

if (File.Exists(f)) { DoSomething(f) }(或否定)是一种反模式.可以在这两个语句之间删除或创建文件,因此检查它的存在是没有意义的.

除此之外,正如评论中指出的那样,虽然File.Exists()可能返回true,但实际打开文件仍然会因各种原因而失败.所以你必须重复错误检查并抛出文件的开头.

因为你不想重复自己,而是保持你的代码干,只是尝试打开文件然后new FileStream()抛出.然后您可以捕获异常,如果您愿意,可以重新抛出原始异常或抛出特定于应用程序的异常.

当然,呼叫File.Exists()是合理的,但不是这种模式.

  • 在检查文件是否存在并立即尝试打开它时,通常是反模式,如果其他逻辑将检查和打开分开,我不认为它是反模式.在某些网络系统上,检查文件的明显可用性可能比获取打开它所需的锁更便宜.如果除非有多个文件可用,代码将无法执行任何有用的操作,在获取打开其中任何文件所需的锁之前,确保所有文件似乎都可用是很有用的. (8认同)
  • @CodeCaster当然可以.而其他一些进程可以在`File.Open(f);`throw和你捕获它之间创建文件.问题是在处理之前情况可能会发生变化(因为在故障情况下这几乎是*不可避免),而是你应该错误检查一次以避免重复(并且你必须*无论如何都要在错误检查).(另请注意,在与某些文件系统交谈时,成功打开并不意味着文件不会被删除:所以即使在打开之后也可​​能发生故障.) (3认同)
  • Python有一个名为"更容易要求宽恕而非许可"的政策(EAFP).这意味着有时候,由于竞争条件和你无法控制的事情,最好只是让你的程序做它想做的事情,并处理那里可能出现的所有错误(例外)而不是检查每一步是否条件是最佳的.在这个例子中,我认为EAFP可以应用于最佳实践. (3认同)
  • 除了竞争条件之外,此代码忽略了file*存在*但不可读*(因为权限等),甚至可能更多错误的情况. (2认同)

Ian*_*ose 15

调用你的方法ReadSomeFile并将其filename作为输入,因此抛出一个是合理的FileNotFoundException.因为你不能通过捕获异常然后自己抛出它来添加任何值,只需让.NET抛出它.

但是,如果你的方法是LoadData(databaseName),它必须访问许多文件,捕获异常,并抛出自定义异常可能是有价值的,因为你可以添加databaseName到异常以及其他有用的信息.