Как выбрать наиболее подходящий тип исключения для броска?
Уже есть много вопросов о SO об исключениях, но я не могу найти ответ на мой вопрос. Не стесняйтесь указать мне в сторону другого вопроса, если я пропустил его.
Мой вопрос довольно прост: как другие разработчики (С#) приходят к выбору наиболее подходящего типа исключения для броска? Раньше я написал следующий код:
if (Enum.IsDefined(enumType, value))
{
return (T)Enum.Parse(enumType, value);
}
else
{
throw new ArgumentException(string.Format("Parameter for value \"{0}\" is not defined in {1}", value, enumType));
}
С тех пор я понял, что выбрасывание InvalidEnumArgumentException
, вероятно, было бы более подходящим, если бы я знал о его существовании в то время.
Имеется ли доступный авторитетный ресурс, который помогает разработчикам выбирать типы исключений, или это просто вопрос опыта?
Изменить
Я дал очки Нольдорину за то, что вы предлагали целый ряд идей в хорошо продуманном ответе. Точки могли бы пойти к любому из вас на самом деле - спасибо за все предложения.
Ответы
Ответ 1
Я бы сказал, что это просто для того, чтобы испытать. Есть все еще новые исключения, которые я обнаруживаю каждый так часто, и я уже давно работаю со многими аспектами .NET. Что бы вы хотели, чтобы этот источник вам рассказывал? Выбор подходящего типа исключений может показаться весьма контекстно-зависимым, поэтому я сомневаюсь в том, какой уровень советов он может предложить. Листинг более распространенных будет больше всего, что он мог бы предоставить. Имена и описания Intellisense типов исключений обычно с хорошей ясностью объясняют их сценарии использования.
Моя рекомендация - просто ознакомиться со всеми основными (в частности, те, что указаны в System
, System.IO
и любых других пространствах имен, которые вы часто используете), и изучать другие на этом пути. Я нахожу, что я вообще убираюсь с помощью небольшого количества. Если вы случайно используете более общий тип исключения, если в BCL уже существует более конкретный, то это не является большим преступлением и может быть изменено позже достаточно легко. Если честно, для какой-либо ошибки, которая особенно специфична, вам часто понадобится создать свой собственный класс, наследующий от Exception
в любом случае.
Надеюсь, что это поможет.
Изменить: Если вы хотите получить краткое руководство по очень распространенным, см. страницу Общие классы исключений на MSDN.
Ответ 2
Krzysztof Cwalina имеет хороший пост на этом см. главу "1.1.1 Выбор правильного типа исключения для броска"
PS Обсудите подписку на свой блог. Хорошее чтение!
Чтобы ответить на ваш вопрос: InvalidEnumArgumentException
потому что бросают наиболее конкретное (наиболее производное) исключение, которое имеет смысл.
И вызывающие, которые улавливают ArgumentException, ловят InvalidEnumArgumentException тоже...
Ответ 3
Общие типы исключений и их пояснения
Я думаю, что это, вероятно, поможет вам узнать, какие наиболее подходящие исключения для вас использовать. Вы также можете заглянуть в документацию MSDN для получения дополнительной информации о классе Exception и всех его типах, если вам нужно.
Ответ 4
Если вы посмотрите статью MSDN в System.Exception, в нижней части страницы находится целый список типов исключений BCL которые наследуют Исключение. Это не совсем окончательный список того, что следует использовать для чего - но это дает вам отличное место, чтобы начать проверку типов исключений. Прохождение каждого из них подскажет, для чего они должны использоваться:
Существует также довольно обширная статья об иерархии исключений .NET, найденная по адресу:
На самом деле весь раздел в библиотеке MSDN об обработке и метании исключений довольно хорош:
Ответ 5
Я думаю, что реальный вопрос заключается в том, чтобы спросить себя: "Какого типа исключения я хочу обработать?" Если вы не будете иметь специальную обработку для InvalidEnumArgumentException или ArgumentException, то они не имеют преимущества перед обычным старым Исключением.
Обычно я либо бросаю исключение, либо обертываю исключение в настраиваемом исключении.
Отредактировано для добавления:
В какой-то момент я помню, что руководство от Microsoft заключалось в том, что ваше приложение никогда не должно генерировать исключения для фреймов, а должно только генерировать расширения ApplicationException.
Ответ 6
Обычно я определяю свою собственную структуру исключений, сначала создавая базовое исключение:
class MyProjectNameException:Exception
{
...constructors, etc
}
а затем производные классы для более точных исключений. Таким образом, вы точно знаете, когда ожидать, какое исключение, и знаете, было ли исключение выбрано вами или фреймворком.
Ответ 7
У меня есть большинство распространенных исключений, написанных на открытках на моем столе и использующих их, когда люди пытаются и взаимодействуют со мной таким образом, который является исключительным.
Это действительно хорошая практика для разработки того, какое исключение лучше всего подходит...
Я использую в основном OperationNotSupportedException
Ответ 8
Если вы найдете исключение, которое хорошо подходит, вы можете его использовать.
Если есть сомнения, просто используйте ApplicationException
. Это исключение, предназначенное для кода, который не является частью стандартной библиотеки.
Если исключение не предназначено для стандартизированного использования (например, улавливание базового класса IOException
, чтобы уловить любую ошибку, связанную с I/O), сообщение, которое вы помещаете в исключение, более полезно, чем тип исключение.