Почему бы не поймать общие исключения - PullRequest
24 голосов
/ 16 ноября 2009

Мой VS только что сказал мне;

Предупреждение 2 CA1031: Microsoft.Design: измените «Program.Main (string [])», чтобы перехватывать более конкретное исключение, чем «Exception», или повторно генерируйте исключение.

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

Почему бы мне не перехватить все исключения сразу, чтобы отобразить для пользователя приятное предупреждение: «Что-то пошло не так, не волнуйтесь, я справлюсь с этим, просто наберитесь терпения»?

Редактировать : Только что увидел, что у меня здесь дупе, извините за это Дупе

Edit2 : чтобы прояснить ситуацию; Я выхожу из программы после того, как было обнаружено любое исключение! Я просто не хочу, чтобы мой пользователь видел диалоговое окно «Сообщить в Microsoft», которое появляется, когда в консольном приложении возникает необработанное исключение!

Ответы [ 10 ]

38 голосов
/ 16 ноября 2009

Глотать исключения - опасная практика, потому что:

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

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

Лучшая практика

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

Обрабатывайте ожидаемые исключения на уровне детализации (например: FileNotFoundException), когда это возможно.

Для непредвиденных исключений вы можете сделать одну из двух вещей:

  • Пусть они всплывают нормально и вызывают сбой
  • Поймай их и грациозно провалишься

Изящно провал?

Допустим, вы работаете в ASP.Net и не хотите показывать желтый экран смерти своим пользователям, но также не хотите, чтобы проблемы были скрыты от команды разработчиков.

В наших приложениях мы обычно отлавливаем необработанные исключения в global.asax, а затем регистрируем и отправляем уведомления по электронной почте. Мы также показываем более дружественную страницу ошибок, которую можно настроить в web.config с помощью тега customErrors.

Это наша последняя линия защиты, и если мы получим электронное письмо, мы сразу же начнем.

Этот тип шаблона не аналогичен простому проглатыванию исключений, когда у вас есть пустой блок Catch, который существует только для «притворства», что исключение не произошло.

Другие заметки

В VS2010 появилось нечто, называемое intellitrace, которое позволит вам отправлять по электронной почте информацию о состоянии приложения домой и просматривать код, проверять значения переменных во время исключения и так далее. Это будет чрезвычайно полезно.

14 голосов
/ 16 ноября 2009

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

РЕДАКТИРОВАТЬ: для уточнения различий между компонентами пользовательского интерфейса и компонентами службы или промежуточного ПО.

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

7 голосов
/ 16 ноября 2009

Вы должны обработать точные исключения, которые вы способны обработать, и позволить всем остальным всплыть. Если он отображает сообщение для пользователя, это означает, что вы не совсем знаете, что вы можете сделать.

4 голосов
/ 16 ноября 2009

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

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

Хорошее кодирование - это практика, предполагающая, что люди совершают ошибки. Предполагать, что все «критические» исключения были перехвачены и обработаны, является плохой идеей.

3 голосов
/ 16 ноября 2009

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

Для Main () я бы рассмотрел два случая:

  1. Ваша собственная (отладочная) сборка, в которой вы хотите получить всю информацию об исключениях, которую вы можете получить: не перехватывайте здесь никаких исключений, поэтому отладчик ломается и у вас есть стек вызовов,
  2. Ваши публичные выпуски, в которых вы хотите, чтобы приложение работало нормально: поймайте исключение и отобразите приятное сообщение. Это всегда лучше (для обычного пользователя), чем окно «Отправить отчет».

Чтобы сделать это красиво, просто проверьте, определен ли DEBUG (и определите его, если VS не делает этого автоматически):

#if DEBUG
  yadda(); // Check only specific Exception types here
#else
  try
  {
    yadda();
  }
  catch (Exception e)
  {
     ShowMessage(e); // Show friendly message to user
  }
#endif

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

3 голосов
/ 16 ноября 2009

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

2 голосов
/ 16 ноября 2009

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

MSDN SuppressMessageAttribute

0 голосов
/ 16 ноября 2009

В VS вы можете настроить пользовательскую страницу ошибок, чтобы показывать вашим пользователям, когда что-то идет не так, вместо того, чтобы ловить их в try-catch. Я предполагаю, так как вы используете VS, что вы используете ASP .NET. Если это так, добавьте этот тег в свой Web.Config под тегом System.Web:

<customErrors mode="RemoteOnly" defaultRedirect="~/CustomErrorPage.aspx" redirectMode="ResponseRewrite" />

Вы также можете перехватить все неперехваченные исключения в файле Global.asax (если у вас его еще нет: щелкните правой кнопкой мыши веб-проект, выберите «Добавить элемент» и найдите его). В этом файле есть куча обработчиков событий для всего приложения, таких как «Application_Error», который перехватывает каждое исключение, которое не перехватывается в вашем приложении, поэтому вам не нужно постоянно использовать Try-Catch. Это удобно использовать для отправки себе электронного письма, если возникает исключение, и, возможно, перенаправить их на свою домашнюю страницу или что-то еще, если вы не хотите использовать тег customErrors выше.

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

0 голосов
/ 16 ноября 2009

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

0 голосов
/ 16 ноября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...