Какие исключения следует создавать для недопустимых или неожиданных параметров in.NET?


какие типы исключений должны быть брошены для недопустимых или неожиданных параметров в .NET? когда бы я выбрал один вместо другого?

контроль:

какое исключение вы бы использовали, если у вас есть функция, ожидающая целое число, соответствующее месяцу, и вы прошли в '42'? Будет ли это попадать в категорию "вне диапазона", даже если это не коллекция?

7 136

7 ответов:

мне нравится использовать: ArgumentException,ArgumentNullException и ArgumentOutOfRangeException.

  • ArgumentException – что-то не так с аргументом.
  • ArgumentNullException – аргумент имеет значение null.
  • ArgumentOutOfRangeException – я не использую это много, но общее использование индексации в коллекцию, и дает показатель, который является большим.

есть и другие варианты, которые не так сильно фокусируются на самом аргументе, но скорее судите о вызове в целом:

  • InvalidOperationException – аргумент может быть в порядке, но не в текущем состоянии объекта. кредит идет в STW (ранее Yoooder). Голосуйте ответ как хорошо.
  • NotSupportedException – аргументы, переданные в действительны, но просто не поддерживаются в этой реализации. Представьте себе FTP-клиент, и вы передаете команду, в которой клиент не делает поддержка.

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

Я люблю, когда сообщения об ошибках указывают на помощь, документацию или другие ресурсы. Например, Microsoft сделала хороший первый шаг со своими статьями KB, например " почему я получаю сообщение об ошибке "операция прервана" при посещении веб-страницы в Internet Explorer?". При возникновении ошибки они указывают на статью базы знаний в сообщении об ошибке. То, что они не делают хорошо, это то, что они не говорят вам, почему именно это не удалось.

еще раз спасибо STW (ex Yoooder) за комментарии.


в ответ на ваши последующие действия, я бы бросил ArgumentOutOfRangeException. Посмотрите, что MSDN говорит об этом исключении:

ArgumentOutOfRangeException is заброшенный когда вызывается метод и по крайней мере один из аргументов, переданных в метод не является нулевым ссылка (Nothing в Visual Basic) и не содержит допустимого значения.

Итак, в этом случае, вы передаете значение, но это значение не является допустимым, так как ваш диапазон 1-12. Однако то, как вы документируете это, дает понять, что ваш API бросает. Потому что, хотя я мог бы сказать ArgumentOutOfRangeException, другой разработчик может сказать ArgumentException. Сделайте его легким и документируйте поведение.

Я голосовал за ответ Джоша, но хотелось бы добавить еще один в список:

в зависимости от фактического значения и какое исключение подходит лучше всего:

если это недостаточно точно, просто выведите свой собственный класс исключений из ArgumentException.

ответ Yoooder просветил меня. Вход недействительным если он не действителен в любое время, в то время как вход неожиданный если он не действителен для текущего состояния системы. Так что в более позднем случае an InvalidOperationException - это разумный выбор.

ArgumentException:

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

несколько подклассов также существуют для определенных типов недействительность. Ссылка содержит резюме подтипов и когда они должны применяться.

короткий ответ:
Ни то, ни другое

более длинный ответ:
использование аргумента * Exception (за исключением библиотеки, которая является продуктом на его on, например библиотеки компонентов) - это запах. Исключения должны обрабатывать исключительную ситуацию, а не ошибки и не недостатки пользователя (т. е. потребителя API).

длинный ответ:
Бросать исключения для недопустимых аргументов грубо, если вы не пишете библиотеку.
Я предпочитаю использовать утверждения, по двум (или более) причинам:

  • утверждения не нужно проверять, а бросить утверждений и тестов против ArgumentNullException выглядит смешно (попробуйте).
  • утверждения более лучше связывают запланированную пользу блока, и ближе к исполняемому файлу документация, чем поведение класса спецификация.
  • вы можете изменить поведение нарушение утверждения. Например, в отладочной компиляции окно сообщения отлично, так что ваш QA ударит вас с ним сразу же (вы также получите свой IDE, ломающийся на линии, где это происходит), в то время как в модульном тесте вы можете указать сбой утверждения как сбой теста.

вот как выглядит обработка нулевого исключения (очевидно, саркастическая):

try {
    library.Method(null);
}
catch (ArgumentNullException e) {
    // retry with real argument this time
    library.Method(realArgument);
}

исключения должны использоваться, когда ситуация ожидается, но исключительная (происходят вещи, которые находятся вне контроля потребителя, такие как сбой ввода-вывода). Аргумент * исключение-это указание на ошибка и будет (мое мнение) обрабатываться с помощью тестов и помогать с отладкой.Утверждать

кстати: в этом конкретном случае вы могли бы использовать тип месяца, а не int. C# не хватает, когда речь заходит о безопасности типа (аспект# rulez!) но иногда вы можете предотвратить (или поймать во время компиляции) эти ошибки все вместе.

и да, MicroSoft ошибается в этом.

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

http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx

какой из них работает лучше всего.