Абстрактное исключение супертипа

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 / catch для непосредственного перехвата любой ошибки, поступающей из библиотеки:

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

Это хорошая практика?

Было бы хорошо, если бы Exceptionбыл сделан абстракция?

РЕДАКТИРОВАТЬ: Моя точка зрения здесь заключается в том, что даже если класс исключения отмечен abstract, вы все равно можете поймать его в блоке всеобщего охвата. Делая это абстракция, это только способ запретить программистам создавать «сверхширокое» исключение. Обычно, когда вы добровольно выбрасываете исключение, вы должны знать, что это за тип и почему это произошло. Таким образом, принудительно выбрасывать более конкретный тип исключения.

марко-fiset
источник
3
+1 «Лучший способ предотвратить неправильное использование - сделать такое использование невозможным». - Скотт Мейерс
Стивен Джеурис
3
"Было бы хорошо, если бы Исключение было сделано абстрактным?" - Абсолютно нет, потому что весь существующий код .NET, который использует новое исключение ("..."), сломается. Тем не менее, "Должна ли команда .NET сделать исключение абстрактным для начала?" - возможно, да, но сейчас> 10 лет уже поздно :)
MattDavey

Ответы:

11

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

НО ... при написании небольших демонстрационных приложений или проверочных концепций я не хочу начинать разработку 10 различных подклассов исключений или тратить время на то, чтобы решить, какой класс исключений "лучший" для ситуации. Я предпочел бы просто бросить Exceptionи передать строку, которая объясняет детали. Когда это выбрасывать код, я не забочусь об этих вещах , и если бы я был вынужден заботиться о таких вещах, я бы либо создать свой собственный GenericExceptionкласс и бросить , что везде, или перейти на другой инструмент / язык. Для некоторых проектов я согласен с тем, что создание соответствующих подклассов исключений важно, но не все проекты требуют этого.

FrustratedWithFormsDesigner
источник
Я полностью с тобой согласен, но вопрос неявно задумывался о нетривиальных проектах.
Марко-Фисет
3

Возможность A: Это логически правильно.

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

При этом мы можем считать академический идеал, что цель Exceptionиерархии классов состоит в том, чтобы определить эффект сужения, чтобы можно было поймать только самые конкретные исключения. (то ArgumentNullExceptionесть уже ArgumentException).

Класс Exception не является исключением (игра слов не предназначена). Предполагается, что это будет самое широкое исключение, «супер исключение», которое почти невозможно поймать, поскольку его область действия бесконечно широка. «Исключение» не abstractв том смысле, что исключение не может существовать как единое целое. Это может (хотя, по общему признанию, хорошие случаи еще не определены - см. Возможность B), и, следовательно, должно быть общедоступным.

«Абстрактное» ключевое слово (в чисто академическом смысле) только в том случае , когда базовый класс не имеет смысла сама по себе - то есть FourLeggedAnimal.

Все это в виду, не было бы технической причины делать класс abstract, кроме как быть источником ухудшения для разработчиков .

Возможность B: Дизайн Lock-in / Они не знали

Если MS сделал этот класс абстрактным, у них, возможно, возникли бы проблемы, если бы они передумали в будущем, так как этот класс очень важен для основ языка. Они уже обманывают ApplicationException, так что очевидно , что они ожидали изменения в рекомендациях в будущем. (см. http://blogs.msdn.com/b/kcwalina/archive/2006/06/23/644822.aspx )

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

Кевин Маккормик
источник
«Просто потому, что оно« сверхширокое », оно не абстрактно». ... Но это аргумент ОП не так ли. Разве это не должно быть абстрактным в том смысле, что всегда нужно передавать какое-то указание на тип исключения.
Стивен Джеурис
Хороший вопрос, я обновлю свой ответ соответственно - природа этого вопроса немного сбивает с толку, потому что «абстрактный» - это и ключевое слово языка, и название обсуждаемой концепции.
Кевин Маккормик
@KevinMcCormick: термин «абстрактный» здесь используется как ключевое слово языка. Скажите, пожалуйста, как я могу изменить свой вопрос, чтобы он был понятнее будущим читателям?
Марко-Фисет
Я думаю, что это отличный вопрос. Любая конверсия OO по abstractключевому слову попадает в эту стену. Не уверен ни в каком способе обойти это, кроме обозначения abstractключевого слова с помощью обратных кавычек.
Кевин Маккормик
2
Как «разобщение» класса является переломным изменением?
Конфигуратор