Супер тип абстрактних винятків


17

Якщо кидання System.Exceptionвважається настільки поганим, чому б не булоException робили abstractв першу чергу?

Таким чином, не вдасться зателефонувати:

throw new Exception("Error occurred.");

Це призведе до використання похідних винятків, щоб надати більш детальну інформацію про помилку, що сталася.

Наприклад, коли я хочу надати власну ієрархію виключень для бібліотеки, я зазвичай оголошую абстрактний базовий клас для моїх винятків:

public abstract class CustomExceptionBase : Exception
{
    /* some stuff here */
}

А потім якийсь похідний виняток із більш конкретною метою:

public class DerivedCustomException : CustomExceptionBase
{
    /* some more specific stuff here */
}

Тоді при виклику будь-якого методу бібліотеки можна було б створити цей загальний блок спробувати / ловити, щоб безпосередньо знайти будь-яку помилку, що надходить із бібліотеки:

try
{
    /* library calls here */
}
catch (CustomExceptionBase ex)
{
    /* exception handling */
}

Це хороша практика?

Було б добре, якби Exception зробити його абстрактним?

EDIT: Моя думка тут полягає в тому, що навіть якщо клас винятків позначений abstract, ви все одно можете впізнати його в блоці "catch all". Зробити це абстрактним - це лише спосіб заборонити програмістам кидати "надширокий" виняток. Зазвичай, коли ви добровільно кидаєте виняток, ви повинні знати, що це за тип і чому це сталося. Таким чином, змушуючи викидати більш конкретний тип виключення.


3
+1 "Найкращий спосіб запобігти неправильному використанню - зробити таке використання неможливим." - Скотт Мейєрс
Стівен Єуріс

3
"Було б добре, якби виняток був абстрактним?" - Абсолютно ні, тому що весь існуючий .NET-код, який використовує новий виняток ("..."), зламається. Однак "Чи повинна команда .NET для початку зробити абстрактним виняток?" - Мабуть, так, але зараз> 10 років занадто пізно :)
MattDavey

Відповіді:


11

Я не знаю справжніх причин, чому це було зроблено таким чином, і я певною мірою погоджуюся, що запобігання киданню нескінченно широких винятків було б хорошою справою.

АЛЕ ... при кодуванні невеликих демонстраційних додатків чи підтверджених концепцій я не хочу починати розробляти 10 різних підкласів винятків або витрачати час, намагаючись вирішити, який "найкращий" клас винятків для даної ситуації. Я краще просто кину Exceptionі передаю рядок, що пояснює деталі. Коли це викинутий код, я не переймаюся цими речами, і якби я був змушений піклуватися про такі речі, я б або створив власний GenericExceptionклас і кинув його скрізь, або перейшов до іншого інструменту / мови. Для деяких проектів я погоджуюся, що правильне створення відповідних підкласів винятку є важливим, але не всі проекти цього вимагають.


Я повністю з вами згоден, але питання неявно думало про нетривіальні проекти.
marco-fiset

3

Можливість A: Логічно правильно.

Ви впевнені, що Microsoft, поряд з багатьма іншими, не пропонують викидати new Exception()безпосередньо з безлічі причин.

Зважаючи на це, ми можемо вважати академічним ідеалом, що метою Exceptionієрархії класів є визначення ефекту звуження, щоб можна було знайти лише найбільш конкретні винятки. (тобто ArgumentNullExceptionвужчий ніж ArgumentException).

Клас винятку не є винятком (каламбур не призначений). Він призначений якнайширший виняток, «супервиняток», який майже не може бути зловлений, оскільки його сфера застосування нескінченно широка. "Виняток" це не такabstract в тому сенсі, що Виняток не може існувати як суб'єкт самостійно. Він може (хоча, правда, ще не визначені добрі випадки - див. Можливість В), а тому повинен бути публічно сконструйованим.

"Абстрактне" ключове слово (у суто академічному розумінні) застосовно лише тоді, коли базовий клас самостійно не має сенсу - тобто FourLeggedAnimal .

Все це на увазі, не було б жодної технічної причини робити клас abstract, окрім як джерело загострення для розробників .

Можливість B: Блокування дизайну / Вони не знали

Якщо МС зробив цей клас абстрактним, вони, можливо, зазнали б проблем, якщо вони передумали в дорозі, оскільки цей клас дуже важливий для основ мови. Вони вже захищені ApplicationException, тому передбачувано, що вони також передбачили зміни рекомендації вниз. (див. http://blogs.msdn.com/b/kcwalina/archive/2006/06/23/644822.aspx )

Можуть бути й інші причини (я думаю, можливо, це має відношення до "Роздуму" чи якоїсь іншої технічної причини), тому я роблю цю посаду CW.


"Просто тому, що це" надшироко ", це не абстрактно". ... Але це аргумент ОП, чи не так. Чи не повинно бути абстрактно в тому сенсі, що завжди потрібно передавати певне позначення типу виключення.
Стівен Євріс

Хороший момент, я відповідно оновлю свою відповідь - характер цього питання трохи заплутаний, оскільки "абстрактний" є як мовним ключовим словом, так і назвою обговорюваної концепції.
Кевін МакКормік

@KevinMcCormick: Термін "абстрактний" тут використовується як мовне ключове слово. Скажіть, будь ласка, як я можу змінити своє питання, щоб воно було зрозумілішим для майбутніх читачів?
marco-fiset

Я думаю, що це чудове питання. Будь-яка конверсія OO щодо abstractключового слова потрапляє на цю стіну. Не впевнений у будь-якому способі обійти його, окрім позначення abstractключового слова за допомогою зворотних посилань.
Кевін МакКормік

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