Должен ли мой метод генерировать собственное исключение, или пусть .NET бросает, если файл не существует?

Вот мой код:

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

    var stream = new FileStream(filePath, ....)
    .....
}

Должен ли я сам исключить исключение (см. проверку File.Exists)? FileStream уже будет бросать FileNotFoundException, если файл не существует. Что такое хорошая практика программирования здесь? Анализ кода говорит, что мы должны проверить наши параметры. Но если я передаю этот параметр непосредственно другому методу (мой или чужой код), и этот метод будет генерировать исключение, то в чем преимущество проверки аргумента в моем коде?

Ответ 1

if (File.Exists(f)) { DoSomething(f) } (или его отрицание) является анти-паттерном. Файл может быть удален или создан между этими двумя операторами, поэтому нет смысла проверять его существование таким образом.

Кроме того, как указано в комментариях, в то время как File.Exists() может возвращать true, фактическое открытие файла может по-прежнему сбой по разным причинам. Поэтому вам придется повторить проверку ошибок и бросить вокруг открытия файла.

Как вы не хотите повторять себя, но вместо этого сохраняйте свой код DRY, просто попробуйте открыть файл и пусть new FileStream() throw. Затем вы можете поймать исключение, и, если хотите, повторно выбросить оригинал или выбросить исключение, зависящее от приложения.

Конечно, вызов File.Exists() может быть оправдан, но не в этом шаблоне.

Ответ 2

Ваш метод называется ReadSomeFile и принимает filename в качестве его ввода, поэтому для него разумно выбрасывать FileNotFoundException. Поскольку вы не можете добавить какое-либо значение, поймав исключение, а затем выбросьте его самостоятельно, просто позвольте .NET выбросить его.

Однако, если ваш метод был LoadData(databaseName), и ему нужно получить доступ ко многим файлам, перехватить исключение и выбросить настраиваемое исключение, может быть полезно, поскольку вы можете добавить databaseName к исключению вместе с другой полезной информацией.

Ответ 3

Помимо уже полученных ответов, вы также можете сказать, что это зависит от того, что вы ожидаете.

Если вы хотите прочитать файл журнала, и он не существует, вы хотите выбросить ошибку или просто пустой String (или пустой массив String)?

Если вы возвращаете значение по умолчанию (например, пустую строку), я бы просто обернул содержимое функции в try-catch (но только ожидаемые ошибки) и вернул значение по умолчанию в блок catch, возвращая фактическое содержимого в блоке try.

Это оставило бы три возможные ситуации:

  • Возвращается содержимое файла;
  • Возвращается значение по умолчанию, поскольку произошла ожидаемая ошибка;
  • Ошибка вызывается .NET, потому что вы не заметили эту ошибку.

Ответ 4

Позвольте правильному методу попытаться открыть файл, пока вы не имеете представления о полном имя файла, что-то вроде специальных имен файлов (например, Файлы устройств и UNC-пути):

В некоторых случаях другие методы файлов могут быть неудачными, но открытие файла успешно.

Некоторые примеры для специальных имен файлов:

  • CON
  • NUL
  • COM1, COM2, COM3, COM4
  • \\сервер\папка\file_path
  • \\teela\admin $\ system32 (для доступа к C:\WINNT\system32)
  • C:..\File.txt
  • \\.\COM1
  • % TEMP%
  • и многое другое...