Почему исключения не проверяются в.NET?

Я знаю, Google, я могу найти подходящий ответ, но я предпочитаю прислушиваться к вашим личным (и, возможно, техническим) мнениям.
В чем основная причина различия между Java и C# в создании исключений?
В Java сигнатура метода, который выбрасывает исключение, должна использовать ключевое слово throws, тогда как в C# во время компиляции вы не знаете, может ли быть выброшено исключение.

10 ответов

Решение

Потому что ответ на проверенные исключения почти всегда:

try {
  // exception throwing code
} catch(Exception e) {
   // either
   log.error("Error fooing bar",e);
   // OR
   throw new RuntimeException(e);
}

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

В статье "Проблема с проверенными исключениями" и собственным голосом Андерса Хейлсберга (дизайнера языка C#) есть три основные причины, по которым C# не поддерживает проверенные исключения, так как они обнаружены и проверены в Java:

  • Нейтрально для проверенных исключений

    "C# практически ничего не говорит о проверенных исключениях. Как только будет найдено лучшее решение - и, поверьте мне, мы продолжим думать об этом, - мы можем вернуться и действительно что-то поставить на место ".

  • Управление версиями с проверенными исключениями

    "Добавление нового исключения в предложение throws в новой версии нарушает код клиента. Это похоже на добавление метода в интерфейс. После того, как вы опубликуете интерфейс, он для всех практических целей будет неизменным… "

    "Забавно, что люди думают, что важная вещь об исключениях - это их обработка. Это не главное в исключениях. В хорошо написанном приложении есть соотношение десять к одному, на мой взгляд, попытка наконец-то попытаться поймать. Или в C#, using заявления, которые, как попытаться, наконец.

  • Масштабируемость проверенных исключений

    "В небольших проверенных исключениях очень заманчиво... Проблема начинается, когда вы начинаете строить большие системы, в которых вы говорите с четырьмя или пятью различными подсистемами. Каждая подсистема выдает от четырех до десяти исключений. Теперь, каждый раз, когда вы идете вверх по лестнице агрегации, у вас есть экспоненциальная иерархия ниже ваших исключений, с которыми вам приходится иметь дело. В итоге вам приходится объявлять 40 исключений, которые вы можете выбросить... Это просто раздувается из-под контроля ".

В своей статье " Почему C# не имеет спецификаций исключений? ”, Anson Horton (менеджер программ Visual C#) также перечисляет следующие причины (подробности по каждому пункту см. В статье):

  • Versioning
  • Производительность и качество кода
  • Непрактичность того, чтобы автор класса различал проверенные и непроверенные исключения
  • Сложность определения правильных исключений для интерфейсов.

Интересно отметить, что C#, тем не менее, поддерживает документирование исключений, генерируемых данным методом через <exception> тег и компилятор даже пытаются потрудиться, чтобы убедиться, что ссылочный тип исключения действительно существует. Однако на сайтах вызовов или при использовании метода проверки не выполняются.

Возможно, вы также захотите взглянуть на Искатель Исключений, который представляет собой коммерческий инструмент Red Gate Software, который использует статический анализ для определения и сообщения об исключениях, генерируемых методом, и который потенциально может остаться незамеченным:

Охотник за исключениями - это новый инструмент анализа, который находит и сообщает набор возможных исключений, которые могут генерировать ваши функции - еще до того, как вы отправите их. С его помощью вы можете легко и быстро найти необработанные исключения, вплоть до строки кода, которая генерирует исключения. Получив результаты, вы можете решить, какие исключения необходимо обработать (с некоторым кодом обработки исключений), прежде чем выпускать приложение в открытый доступ.

Наконец, у Брюса Экеля, автора книги " Мышление в Java", есть статья " Нужны ли в Java проверяемые исключения? ”, Это также может стоить прочитать, потому что вопрос о том, почему в C# нет проверенных исключений, обычно укореняется в сравнении с Java.

Основная философия проектирования C# заключается в том, что на самом деле перехват исключений редко бывает полезен, тогда как очистка ресурсов в исключительных ситуациях довольно важна. Я думаю, что будет справедливо сказать, что using (шаблон IDisposable) является их ответом на проверенные исключения. Смотрите [1] для получения дополнительной информации.

  1. http://www.artima.com/intv/handcuffs.html

К моменту разработки.NET Java уже довольно долго проверяла исключения, и разработчики Java в лучшем случае рассматривали эту функцию как спорный спорный. Таким образом, дизайнеры.NET решили не включать его в язык C#.

Фундаментально, должно ли обрабатываться исключение или нет, является свойством вызывающей стороны, а не функции.

Например, в некоторых программах нет никакого смысла в обработке IOException (рассмотрите специальные утилиты командной строки для выполнения перехвата данных; они никогда не будут использоваться "пользователем", они - специализированные инструменты, используемые специалистами). В некоторых программах целесообразно обрабатывать IOException в точке, расположенной "близко" к вызову (возможно, если вы получите FNFE для своего конфигурационного файла, вы вернетесь к некоторым значениям по умолчанию, или посмотрите другое место, или что-то подобное). природа). В других программах вы хотите, чтобы он долго пузырился перед обработкой (например, вы можете прервать его до достижения пользовательского интерфейса, после чего он должен предупредить пользователя о том, что что-то пошло не так.

Каждый из этих случаев зависит от приложения, а не от библиотеки. И все же, за проверенными исключениями, именно библиотека принимает решение. Библиотека Java IO принимает решение, что она будет использовать проверенные исключения (которые настоятельно рекомендуют обработку, которая является локальной для вызова), когда в некоторых программах лучшей стратегией может быть нелокальная обработка или вообще отсутствие обработки.

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

Интересно, что ребята из Microsoft Research добавили проверенные исключения в SpeC#, их расширенный набор C#.

Сам Андерс отвечает на этот вопрос в этом эпизоде радиоподкаста по программной инженерии.

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

Я перешел с Java на C# из-за смены работы. Сначала я немного беспокоился о разнице, но на практике это не имело значения.

Может быть, это потому, что я пришел из C++, в котором есть объявление об исключении, но оно обычно не используется. Я пишу каждую строчку кода, как если бы он мог генерировать - всегда использую использование с Disposable и думаю об очистке, которую я должен сделать в конце концов.

Оглядываясь назад, можно сказать, что распространение объявления throws в Java ничего мне не дало.

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

Я иногда пропускаю проверенные исключения в C#/.NET.

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

Другие вопросы по тегам