С#: Должен ли я бросать исключение ArgumentException или DirectoryNotFoundException?

У меня есть метод, который принимает путь к каталогу как строку. В начале метода он проверяет, существует ли этот путь, и если он не должен вызывать исключение. Я думаю, что это должно быть, возможно, выбросить DirectoryNotFoundException или что-то вместо менее конкретного ArgumentException.

Я прочитал документацию msdn этого DirectoryNotFoundException, и он говорит, что

DirectoryNotFoundException использует HRESULT COR_E_DIRECTORYNOTFOUND, который имеет значение 0x80070003.

Я не знаю, что это значит, и это выглядит немного страшно... Должен ли я все-таки выбросить это исключение, или я должен придерживаться обычного ArgumentException? Или я должен придерживаться ArgumentException просто потому, что это аргумент, о котором я жалуюсь? Или?

public void MakeFunOf(string path)
{
    if(!Directory.Exists(path))
        throw new WhatException();
    TellJokeAbout(path);
    PointAndLaughAt(path);
}

Ответы

Ответ 1

Если вы ожидаете, что разработчик проверит наличие каталога перед вызовом вашего метода, используйте ArgumentException. Если вы хотите, чтобы у разработчика был выбор обработки отсутствующего каталога, используйте исключение DirectoryNotFound.

Другими словами, "Это ошибка, которую разработчик сказал мне получить доступ к каталогу, который не существует?"

Лично я использовал бы исключение DirectoryNotFound.

Ответ 2

По-моему, вы должны проверить правильность аргумента и выкинуть ArgumentException, а затем проверить флажок DirectoryNotFoundException. Это большая разница, если аргумент не был указан или был указан только неправильный путь.

void CheckDir(string path)
{
  if(String.IsNullOrEmpty(path))
  {
    throw new ArgumentException("Path not specified.");
  }
   if(!Directory.Exists(path))
  {
    throw new DirectoryNotFoundException();
  }
}

Ответ 3

Это просто мое мнение (поскольку у меня нет ничего конкретного, чтобы поддержать его), но вот мои причины бросать DirectoryNotFoundException, а не ArgumentException:

  • Вы должны бросить наиболее конкретный/точный тип исключения, чтобы вы могли позволить потребителю вашего кода понять причину исключения исключений.
  • Учитывая, что методы Framework будут вызывать исключение DirectoryNotFoundException, когда вы пытаетесь сделать что-то с отсутствующим каталогом, а не с аргументом ArgumentException, следуйте предложении Framework

Ответ 4

Похоже, вы должны бросать DirectoryNotFoundException, поскольку ArgumentException лучше использовать, если указанный параметр не указан.... т.е. его нулевое значение.

Другой вариант - создать собственное исключение и выбросить его вместо этого.

[Serializable]
public class InvalidConfigurationException: Exception
{
    public InvalidConfigurationException() : base()
    {
    }

    public InvalidConfigurationException(string message)
        : base(message)
    {
    }

    public InvalidConfigurationException(string message, Exception innerException)
        : base(message, innerException)
    {
    }

    protected InvalidConfigurationException(SerializationInfo info, StreamingContext context) 
        : base(info, context) 
    { 
    }
}

Тогда вы могли бы сделать:

public void MakeFunOf(string path)
{    
   if(!Directory.Exists(path))        
       throw new InvalidConfigurationException('Directory entered was invalid or does not exist');
   TellJokeAbout(path);    
   PointAndLaughAt(path);
}

Ответ 5

Ссылаясь на документацию 'ArgumentException':

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

К букве это означает, что выбор исключений зависит от спецификации/документации вашего метода.

Если параметр пути документирован как нечто вроде "Путь к существующему файлу/директории", тогда вам будет оправдано бросать "ArgumentException" (или производную), потому что в основном благодаря документации, которую вы сделали вызывающим ответственный за обеспечение того, что файл на самом деле там.

Если параметр пути документирован более широко как "Путь к файлу, в который нужно шутить и смеяться", то я бы сказал, что "DirectoryNotFoundException" более подходит.