




Я не уверен, почему «технически», но допустим, у меня есть приложение / веб-сайт, использующий разрешения. Если у кого-то нет нужного разрешения, глупо генерировать исключение DivideByZero или IOException. Вместо этого я могу создать свое исключение AccessDeniedException, которое поможет мне отладить позже.
Так что вы также можете бросить их самостоятельно, а затем поймать их и узнать точно, что они означают.
Также: если вы создаете библиотеку классов / framework / api, часто бывает полезно создать BaseException, от которого наследуются другие исключения в вашем коде. Затем, когда ваш код вызывает исключения, программисты, которые его используют, могут быстро узнать источник исключения.
Потому что это может прояснить ваши намерения, и вы также можете отслеживать использование с помощью функциональности IDE. Предположим, у вас есть настраиваемая серверная система под названием «FooBar» и вы создаете «FooBarDownException», вы можете отслеживать использование этого исключения, чтобы идентифицировать любую настраиваемую логику, содержащуюся в вашем приложении, потому что FooBar не работает. Вы можете перехватить этот конкретный тип исключения и игнорировать другие, избегая перегрузок и условной логики в обработчиках исключений. На самом деле это просто еще одна версия строгой типизации. Это также означает, что вы можете избежать комментариев в своем коде, потому что исключение имеет намерение раскрыть имя.
Я бы не сказал, что функциональность IDE - это аргумент в пользу продажи, но наиболее важной причиной является ясность намерений.
ИМХО строгая типизация позволяет действительно Работа с кодом и делать его лучше, позволяя непрерывный рефакторинг. Так что инструменты важны.
Что это значит, когда мы говорим о ясных намерениях? Я могу видеть использование дорожек, так как это обнаружит все области, которые могут быть затронуты из-за того, что FooBar не работает (используемый стандартный тип исключения, такой как ArgumentException, во многих разных случаях не дает этого преимущества).
По той же причине, по которой вы бы создали разные коды выхода для приложения, отличного от .NET: чтобы указать разные ошибки, специфичные для приложения. Типа ... ConnectionBrokenException или гм ... UserSmellsBadException ... или что-то в этом роде.
Таким образом, вы можете точно знать, что пошло не так, и действовать соответствующим образом. Например, если вы пытаетесь отправить некоторые данные, а класс транспорта данных выдает ConnectionBrokenException, вы можете открыть диалоговое окно повторного подключения и попытаться восстановить соединение. Затем метод повторного подключения вызовет ConnectionTimeoutException, если он истечет, и вы снова сможете действовать соответствующим образом.
Стандартные исключения .NET не охватывают всего плохого, что может пойти не так в любом приложении, и не предназначены для этого. Если ваша программа не очень проста, вероятно, вам придется создать как минимум несколько пользовательских исключений.
Как писал Джоэл: «Так что вы также можете бросить их сами, а затем поймать их и точно знать, что они означают».
Кроме того, вы можете добавить конкретную информацию о проблеме, чтобы обработчик исключений действовал более точно.
Недавно я сделал длинную запись в блоге на эту тему:
http://blogs.msdn.com/jaredpar/archive/2008/10/20/custom-exceptions-when-should-you-create-them.aspx
Суть этого сводится к следующему: создавать собственное исключение только в том случае, если верно одно из следующих условий.
Конкретные таможенные исключения позволяют выделить различные типы ошибок для отчетов о перехвате. Общая конструкция для обработки исключений такова:
try
{}
catch (Exception ex)
{}
Это перехватывает исключения все независимо от типа. Однако, если у вас есть собственные исключения, вы можете иметь отдельные обработчики для каждого типа:
try
{}
catch (CustomException1 ex1)
{
//handle CustomException1 type errors here
}
catch (CustomException2 ex2)
{
//handle CustomException2 type errors here
}
catch (Exception ex)
{
//handle all other types of exceptions here
}
Следовательно, определенные исключения позволяют более точно контролировать обработку исключений. Это преимущество распространяется не только на настраиваемые исключения, но и на все другие типы исключений в системных библиотеках .NET.
Во-первых, исключения реализованы в библиотеке, а не в языке - как они могут создавать исключения в библиотеке? Я почти уверен, что вы не выступаете за то, чтобы системные библиотеки имели другой набор правил.
Во-вторых, действительно возможно использовать объектное дерево исключений. Ваши унаследованные исключения могут иметь специальные атрибуты, если хотите - их можно использовать для более сложных вещей, чем они есть. Я не защищаю, чтобы они использовались как общий механизм передачи данных или что-то в этом роде (хотя они могли бы быть), но я мог видеть случай, когда кто-то реализовал настраиваемое решение для ведения журнала, которое требовало специального атрибута в исключении ...
Ваши пользовательские исключения могут содержать флаг, указывающий на особую обработку (возможно, тот, который говорит, что вам следует перезапустить JVM), они могут содержать информацию об уровнях ведения журнала и многое другое.
В любом случае, я не защищаю эти вещи, я просто говорю, что это возможно. Первый абзац - это ваш настоящий ответ.
Вы не должны этого делать, если встроенные исключения правильно описывают проблему / исключение. Я бы не стал создавать свои собственные базовые классы для создания собственных ArgumentException, ArgumentNullException или InvalidOperationException.
Вы можете создавать свои собственные исключения и описывать ошибку на более высоком уровне. однако это обычно не очень помогает при отладке из потребительского класса.
Если вы сами генерируете и перехватываете исключение, может потребоваться настраиваемое исключение.
Еще одна причина, когда клиент разговаривает с интерфейсами. Поскольку клиент не осведомлен о реализациях интерфейса и, возможно, они могут генерировать разные исключения, это хорошее место для создания пользовательских исключений для унификации выдаваемых ошибок.
Я писал об этом частном случае:
http://blog.mikecouturier.com/2010/01/creating-custom-exceptions-in-net-right.html
Мне не нравится использование InvalidOperationException (или, если на то пошло, большинства исключений Framework) для условий, в которых вызывающий может попытаться обработать и восстановить. Проблема в том, что даже если метод задокументирован как бросание InvalidOperationException в известное состояние системы, также возможно, что какой-нибудь вызываемый изнутри метод может выдать InvalidOperationException, когда состояние системы повреждено. Жаль, что ни один из языков .net или Java не позволяет объявлять исключения как «проверенные» <i> на сайте throw </i> с семантикой, которая могла бы ...
... укажите, что оператор catch должен <i> только </i> перехватывать проверенные исключения, и что проверенные исключения, которые не были пойманы или иным образом помечены для передачи по цепочке вызовов, станут непроверенными исключениями (так что catch, окружающий вызов метода Foo() мог легко отличить InvalidOperationException, который был сгенерирован по той причине, которую ожидает Foo(), от того, который был сгенерирован внутренним методом по причинам, которых Foo() не ожидал.
В качестве помощи для возможного повторного открытия этого вопроса из Как: создавать пользовательские исключения в MSDN: «Если вы хотите, чтобы пользователи могли программно различать некоторые состояния ошибки, вы можете создавать свои собственные определяемые пользователем исключения».