Что такое ApplicationException для .NET?

172

Чтобы генерировать исключения, я обычно использую встроенные классы исключений, например, ArgumentNullExceptionи NotSupportedException. Однако иногда мне нужно использовать пользовательское исключение, и в этом случае я пишу:

class SlippedOnABananaException : Exception { }
class ChokedOnAnAppleException : Exception { }

и так далее. Затем я бросаю и ловлю их в своем коде. Но сегодня я наткнулся на ApplicationExceptionкласс - должен ли я использовать это вместо этого? Для чего это?

Кажется неэффективным иметь множество эффективно идентичных классов исключений с разными именами (мне обычно не нужны какие-то отдельные функции). Но мне не нравится идея поймать универсальный ApplicationExceptionи использовать дополнительный код для определения ошибки.

Где должен ApplicationExceptionсоответствовать мой код?

Джеймс
источник

Ответы:

100

Согласно замечаниям в MSDN:

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

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

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

Femaref
источник
9
Так что кажется, что ApplicationExceptionэто бесполезно и существует только из-за обратной совместимости?
Beatles1692
Новая документация MSDN, по крайней мере, 4.7.2, пропускает это замечание. Спасибо за слово: D
Алекс
147

Краткий ответ: нигде.

Это пережиток прошлого, когда Microsoft планировала, что разработчики унаследуют все свои пользовательские исключения от ApplicationException. Вскоре после этого они передумали и сообщили, что пользовательские исключения должны быть производными от базового класса Exception. См. Рекомендации по обработке исключений в MSDN.

Одним из наиболее широко распространены причин этого исходит от отрывка из Джеффри Рихтер в Руководстве по проектированию рамочного :

System.ApplicationException - это класс, который не должен быть частью .NET Framework. Первоначальная идея заключалась в том, что классы, производные от SystemException, будут указывать исключения, выбрасываемые из самого CLR (или системы), тогда как исключения без CLR будут производными от ApplicationException . Однако многие классы исключений не следовали этому шаблону. Например, TargetInvocationException (который генерируется CLR) является производным от ApplicationException . Таким образом, класс ApplicationException потерял всякий смысл. Причина для наследования этого базового класса состоит в том, чтобы позволить некоторому коду выше стека вызовов перехватывать базовый класс. Больше невозможно было перехватить все исключения приложения.

Так что у вас есть это. Резюме заключается в том, что ApplicationException не является вредным , просто бесполезным .

Быстрый Джо Смит
источник
2
Кто-нибудь знает, почему это так? Кажется, что это имеет смысл, чтобы вы могли отображать исключения App, но не исключения «запрограммирован программистом».
Джош Кодрофф
9
Кстати, из этого объяснения видно, что это не плохой дизайн как таковой, но что MSFT испортил реализацию. Кто-нибудь еще читает это аналогично?
Джош Кодрофф
8
@JoshKodroff: Я думаю, что проблема в том, что если приложение Whizbangрешит, что оно хочет иметь все свои исключения в некоторой общей иерархии, использование ApplicationExceptionдля этой цели действительно не даст никаких преимуществ по сравнению с использованием пользовательского WhizbangExceptionбазового класса. Однако более серьезная проблема в иерархии исключений .net ApplicationExceptionсвязана не с тем, а с тем, что не удалось разделить исключения по категориям, которые могут быть фатальными для приложений, фатальными для потоков и локальными проблемами, а также неспособностью значимые «составные» исключения.
суперкат
@JoshKodroff: В правильно спроектированной структуре исключений, IMHO, если исключение выдается во время finallyблока, в то время как другое исключение ожидает, catchблоки дальше в стеке вызовов должны быть запущены, если они соответствуют любому вложенному исключению, но оставляют другие исключения ожидающими, чтобы выйти catchблок будет переходить к другому catchблоку в пределах того же tryблока (если таковые были пригодны), и выходом из finallyблока с какими - либо исключениями , ожидающих бы перейти к следующему внешнего catchили finally.
суперкат
2
@JoshKodroff Есть еще одна вещь, которой я удивляюсь, не привлекай больше внимания. Что такое «приложение» на самом деле? А как насчет сторонних библиотек ? Поскольку они не являются частью .Net Framework, они должны в соответствии с оригинальными рекомендациями наследоваться от ApplicationException. Теперь, когда вы используете эту библиотеку в своем приложении, а также создаете свои собственные исключения ApplicationExceptions, вы больше не можете различать свои собственные исключения из исключения библиотеки на основании этого. Так что это бесполезно. Вместо этого каждый компонент должен просто определять свой собственный базовый тип исключения, как описывает суперкат.
Оскар Берггрен
22

В первоначальном проекте, в .NET 1.0, планировалось, что сама структура будет генерировать SystemExceptionи получать; пока пользовательские приложения - скинут ApplicationExceptionи выведут.

Но позже, в .NET 2.0, это было отброшено.

Таким образом, производные от Exception.

abatishchev
источник