Какие исключения следует создавать для недопустимых или неожиданных параметров in.NET?
какие типы исключений должны быть брошены для недопустимых или неожиданных параметров в .NET? когда бы я выбрал один вместо другого?
контроль:
какое исключение вы бы использовали, если у вас есть функция, ожидающая целое число, соответствующее месяцу, и вы прошли в '42'? Будет ли это попадать в категорию "вне диапазона", даже если это не коллекция?
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
(что-то не так с значение)
ArgumentNullException
(аргумент null, пока это не разрешено)
ArgumentOutOfRangeException
(аргумент имеет значение вне допустимого диапазона)если это недостаточно точно, просто выведите свой собственный класс исключений из
ArgumentException
.ответ Yoooder просветил меня. Вход недействительным если он не действителен в любое время, в то время как вход неожиданный если он не действителен для текущего состояния системы. Так что в более позднем случае an
InvalidOperationException
- это разумный выбор.
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
какой из них работает лучше всего.