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


172

Щоб кинути винятки, я зазвичай використовую вбудовані класи виключень, наприклад, ArgumentNullExceptionта NotSupportedException. Однак іноді мені потрібно використовувати спеціальний виняток, і в такому випадку я пишу:

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

і так далі. Потім я кидаю і ловлю їх у своєму коді. Але сьогодні я натрапив на ApplicationExceptionзаняття - чи варто використовувати це замість цього? Для чого це?

Це здається неефективним мати безліч ефективно однакових класів винятків з різними іменами (мені зазвичай не потрібні окремі функціональні можливості). Але мені не подобається ідея ловити загальне ApplicationExceptionта використовувати додатковий код, щоб визначити, у чому помилка.

Де має ApplicationExceptionвідповідати моєму коду?


35
Відмінне запитання, також +1 за хитро названі вибіркові винятки
Коді Грей

Відповіді:


100

Відповідно до зауважень у msdn:

Користувацькі програми, а не загальна мова виконання, кидають спеціальні винятки, похідні з класу ApplicationException. Клас ApplicationException розрізняє винятки, визначені програмами, та винятки, визначені системою.

Якщо ви розробляєте програму, якій потрібно створити власні винятки, вам рекомендується отримати спеціальні винятки з класу «Винятки». Спочатку вважалося, що спеціальні винятки мають походити з класу ApplicationException; однак на практиці це не знайшло значної цінності. Для отримання додаткової інформації дивіться статтю Кращі практики поводження з винятками.

Отримати їх від Exception. Крім того, я не бачу проблем зі створенням нових винятків для ваших випадків, якщо це гарантовано. Якщо у вас трапляється випадок, коли в рамках вже є виняток, скористайтеся цим, інакше прокатуйте свій власний.


9
Тож здається, що ApplicationExceptionце марно і чи є це лише через відсталу сумісність?
Бітлз" 1692,

Нова документація MSDN, принаймні 4.7.2, не вистачає цього зауваження. Дякую за qutoe: D
Алекс

147

Коротка відповідь: нікуди.

Це пережиток минулого, коли Microsoft задумав розробників успадкувати всі власні винятки з ApplicationException. Незабаром вони передумали і порадили, що спеціальні винятки повинні походити з базового класу винятків. Див. Кращі практики поводження з винятками на MSDN.

Однією з найбільш широко розповсюджених причин цього є поправка Джеффі Ріхтера в Радянських рекомендаціях щодо дизайну :

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

Так ось у вас це є. Резюме полягає в тому, що ApplicationException не є шкідливим , а просто марним .


2
Хтось знає, чому це? Здається, це має сенс, щоб ви могли відображати винятки з програми, але не "програміст накрутив" винятки.
Джош Кодрофф

9
До речі, з цього пояснення випливає, що це не поганий дизайн сам по собі, але що MSFT накрутив реалізацію. Хтось ще читає це аналогічно?
Джош Кодрофф

8
@JoshKodroff: Я думаю, що проблема полягає в тому, що якщо програма Whizbangвирішить, що вона хоче мати всі свої винятки в рамках якоїсь загальної ієрархії, використання ApplicationExceptionдля цієї мети дійсно не дасть переваги перед використанням користувацького WhizbangExceptionбазового класу. Більш серйозна проблема в ієрархії винятків .net полягає не в ApplicationExceptionтому, а в тому, що вони не розділяють винятки на категорії, що ймовірно-застосовні, ймовірно, нитки-фатальні та локальні проблеми, а також неможливість мати змістовні "складені" винятки.
supercat

@JoshKodroff: У правильно розробленому рамках винятків IMHO, якщо виняток буде викинуто під час finallyблоку, поки очікується інший виняток, catchблоки подалі вгору стека виклику повинні спрацьовувати, якщо вони відповідають будь-яким вкладеним виняткам, але залишати інші винятки в очікуванні, так що вихід catchблок буде переходити до іншого catchблоку в межах того ж tryблоку (якщо такі були придатні), і виходом з finallyблоку з якими - або винятками , які очікують б перейти до наступного зовнішнього catchабо finally.
supercat

2
@JoshKodroff Є ще одна річ, на яку я дивуюсь, що не приділяють більше уваги. Що таке насправді "додаток"? А як щодо сторонніх бібліотек ? Оскільки вони не є частиною рамки .Net, вони, згідно з оригінальними вказівками, повинні успадковувати програму ApplicationException. Тепер, коли ви використовуєте цю бібліотеку у вашій програмі, а також створюєте власні ApplicationExceptions, ви більше не можете розпізнавати власні винятки з виключення бібліотеки на основі цього. Тож марно. Натомість кожен компонент повинен просто визначити власний базовий тип винятку, як описується суперката.
Оскар Берггрен

22

У початковому дизайні, в .NET 1.0, планувалося, що сам фреймворк буде кинутим SystemExceptionі виведеним; в той час як користувацькі програми - будуть кидати ApplicationExceptionі виводити.

Але пізніше, у .NET 2.0 це було відмінено.

Таким чином походять від Exception.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.