Какие факторы следует учитывать при написании настраиваемого класса исключений?

Когда пользовательские классы исключений наиболее ценны?
Существуют ли случаи, когда их следует или не следует использовать? Каковы преимущества?

Связанные вопросы:

Ответ 1

Вопросы, которые нужно задать себе:

  • Кто это поймает? Если никто, то вам действительно не нужно специальное исключение.
  • Куда вы его бросите? Достаточно ли доступно контекст, или вам нужно будет ловить и повторно бросить несколько раз, прежде чем исключение будет полезно для конечного зрелища?
  • Почему вы его бросаете? Потому что вы поймали исключение и вам нужно приложить дополнительную информацию? Поскольку в некоторых данных вы столкнулись с невосстановимой ошибкой и вам нужно сообщить о специфике кода клиента? Потому что вам нравится throw вещи?
  • Какое исключение? Не то, что вызвало это, но что это такое с точки зрения ловца? Что-то, что они могут исправить и повторить? Что-то, что они никогда не должны повторять? Что-то, о чем они должны уведомить пользователя? Что-то они должны приложить к контекстной информации, а затем повторно бросить? Что определяет информацию, которую вам нужно передать, если есть...

Заповеди:

  • Не тратьте время на пользовательские исключения, которые никогда не будут пойманы.
  • Не исключайте "удвоение" исключений: каждый настраиваемый тип исключения должен иметь четко определенный случай, когда он может и должен быть пойман; исключения, которые не совпадают, должны быть разбиты на их собственные пользовательские типы (а не, скажем, заставлять зрелище создавать условную логику в одном предложении catch()).
  • Если у вас нет веских оснований, всегда разрешайте прикреплять внутреннее исключение/данные из ранее застигнутого исключения. Конфликт с потерями редко бывает полезен.

Ответ 2

Я немного минималистский и создаю настраиваемое исключение, если есть код вызова, который должен явно реагировать на конкретное условие, которое произошло. Для всех остальных ситуаций я использую наиболее подходящее исключение библиотеки .NET. Например. ArgumentNullException, InvalidOperationException

Ответ 3

Когда вам нужно каким-то образом отличить одно исключение от других. Что это, действительно. Конечно, вы можете создать класс исключения, который также использует перечисление, чтобы отличать его причину.

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

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

Ответ 4

Как Wheelie сказал, посмотрите сначала на соответствующее исключение рамки и используйте только исключения (особенно пользовательские исключения), где вы действительно планируете их поймать.

Я использую специальный класс исключений, который содержит свойство UserMessage, чтобы я мог распространять проблему на понятном для пользователя языке, когда это возможно.

Если вы используете .NET, проверьте Конструирование пользовательских исключений. Интересно, что документация изменила ее рекомендацию на использование ApplicationException:

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

Ответ 5

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

Ответ 6

Моя основная причина использования пользовательских исключений - это инкапсуляция с несколькими провайдерами: наличие утечки SqlException из уровня SqlDataAccess, а SocketException из уровня NetworkDataAccess делает код вызова зависимым от данных вашего реализация. Лучше обернуть их в DataAccessException или что-то еще.

Ответ 7

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

У меня также есть второе правило, которое я применяю: "Создайте только настраиваемое исключение, если вы ожидаете, что разработчик сможет обработать исключение". Нет смысла создавать новое исключение, если вы не считаете исключение восстановимым условием. В этом контексте более эффективно использовать InvalidOperationException.

EDIT: закончил писать запись в блоге на эту тему: http://blogs.msdn.com/jaredpar/archive/2008/10/20/custom-exceptions-when-should-you-create-them.aspx