Всегда ли плохо ловить System.Exception? - PullRequest
11 голосов
/ 30 июня 2011

Пожалуйста, рассмотрите следующий фрагмент кода, который выдает три разных исключения (а именно, System.Configuration.ConfigurationErrorsException, System.FormatException и System.OverflowException):

int SomeInt = Convert.ToInt32(ConfigurationManager.AppSettings["SomeIntValue"]);

Исключения разные, и поэтому на практикеУ меня должно быть три разных блока catch для обработки каждого конкретного исключения.Тем не менее, в этом конкретном случае все исключения обрабатываются одинаково: журнал записывается, скажем, в EventViewer, и отображается сообщение, информирующее об ошибке конфигурации ... В этом конкретном случае это слишком плохо для использования

try
{
    int SomeInt = ConfigurationManager.AppSettings["SomeIntValue"];
}
catch (Exception ThisException)
{
    /* Log and display error message. */
}

или я должен вместо этого использовать три блока catch и повторить код внутри каждого из них?

Ответы [ 6 ]

8 голосов
/ 30 июня 2011

См. Обработка исключений в C # Fallout для обсуждения этой проблемы.

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

Обновление (и немного выходит за рамки)

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

4 голосов
/ 09 апреля 2014

Это плохая практика, чтобы поймать System.Exception.,,или еще лучше, это обработка System.Exception в любом месте, кроме верхнего уровня вашего приложения.То, что вы должны сделать, это:

  1. Catch System.Exception
  2. Проверьте исключение для типов, которые вы планируете обрабатывать одинаково
  3. Rethrow, если это не один из них.

Пример кода:

catch (Exception ex)
{
    if (ex is FormatException || ex is OverflowException || ex is ConfigurationErrorsException) {
        CommonHandler();
    }
    else {
        throw;
    }
}
2 голосов
/ 30 июня 2011

Я не думаю, что это плохая практика. Если желаемая функциональность: «всякий раз, когда этот код генерирует исключение, тогда выполняйте эти действия», я думаю, что перехват System.Exception совершенно уместен.

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

1 голос
/ 02 июля 2011

То, что действительно необходимо, но иерархия исключений .net не обеспечивает, - это чистый способ различения исключений, которые означают «Запрошенная операция не произошла, но состояние системы в основном хорошее, за исключением той степени, которая подразумевается операция не произошла "из тех, которые означают" процессор горит, и даже попытка сохранить работу текущего пользователя, скорее всего, не усугубит ситуацию ". Есть много контекстов, в которых действительно нужно стремиться отловить все исключения первого типа, в идеале не отлавливая исключения второго. Хотя есть несколько градаций, помимо двух приведенных выше, обычно при отлове исключений на самом деле не волнует различие между InvalidArgumentException или InvalidOperationException; то, что заботится о том, является ли общее состояние системы действительным или поврежденным.

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

Между прочим, если бы у меня были мои барабанщики, был бы класс ExceptionBase, из которого могли бы возникнуть все исключения; большинство исключений будет происходить из Exception (которое, в свою очередь, будет происходить из ExceptionBase), но такие вещи, как ThreadAbortException, StackOverflowException, OutOfMemoryException и т. д. будут производными от CriticalException. Таким образом, вы можете поймать большинство «неожиданных» исключений, случайно не подавив действительно плохие.

1 голос
/ 30 июня 2011

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

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

В общем, мысль такова: Нужно ли выполнять другие действия вОтносительно различных типов исключений? Чаще всего ответ отрицательный, поэтому достаточно пустого catch(Exception ex){ /* log... */ } (или даже вообще никакого catch, если исключение неизменно фатально).

Редактировать: пусто, как в бланке, а не в пустом блоке:)

1 голос
/ 30 июня 2011

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

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

Часто пропускаемый шаблон заключается в том, что вы можете поймать, выполнить повторную попытку.

catch(Exception ex)
{
 //do something
 throw;
}

, сохраняя при этом детали исключения.

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