Захват базы Класс исключений в .NET.

Я продолжаю слышать, что

catch (Exception ex)

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

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

EDIT:

Люди говорят, что я должен просмотреть стек вызовов и обрабатывать ошибки конкретно, потому что, например, исключение StackOverflow нельзя обрабатывать осмысленно. Однако остановка процесса - это результат худший, я хочу предотвратить это любой ценой. Если я не могу справиться с StackOverflow, так что это - результат будет не хуже, чем не ловить исключения на всех, и в 99% случаев, информирующее пользователя является наименее плохой вариант, насколько я понимаю

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

Ответ 1

Плохая практика -

catch (Exception ex){}

и варианты:

catch (Exception ex){ return false; }

и др.

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

Ответ 2

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

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

Здесь мое общее правило (и, как и все правила, оно предназначено для разбивки при необходимости):

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

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

Если я ничего не могу сделать об исключении, отличном от ошибки (скажем, база данных отключена), или если исключение действительно неожиданно, поймайте все, возьмите его, зарегистрируйте и быстро выполните сбой, с общее сообщение об ошибке, отображаемое пользователю перед смертью. (Конечно, есть определенные классы ошибок, которые почти всегда будут безуспешно сбой - OutOfMemory, StackOverflow и т.д. Мне повезло, что мне не приходилось иметь дело с теми, что были в коде уровня prod... до сих пор!)

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

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

Ответ 3

Когда я вижу

catch (Exception ex)

моя рука начинает нащупывать молоток. Почти нет оправданий, чтобы поймать базовое Исключение. Мне доступны только действительные случаи:
1) Третий участник выбрасывает исключение (проклятый автор)
2) Обработка исключений верхнего уровня (в крайнем случае) (например, обрабатывать "необработанные" исключения в приложении WinForms)

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

Я бы не согласился с Армином Ронахером. Как бы вы себя чувствовали, если возникло исключение StackOverflow? Попытка выполнить дополнительные действия может привести к еще худшим последствиям. Исключить исключение, только если вы можете справиться с ним значимым и безопасным способом. Catching System.Exception, чтобы охватить диапазон возможных исключений, является ужасно неправильным. Даже когда вы повторно бросаете его.

Ответ 4

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

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

Ответ 5

Это плохая практика в том смысле, что вы не должны делать это повсюду.

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

Ответ 6

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

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

Ответ 7

Совершенно нормально, если вы повторно поднимаете исключения, с которыми вы не можете справиться должным образом. Если вы просто поймаете исключения, вы можете скрыть ошибки в коде, которого вы не ожидаете. Если вы поймаете исключения, чтобы отобразить их (и обойти поведение die-and-print-traceback-to-stderr), что вполне приемлемо.

Ответ 8

Я думаю, что плакат ссылается на обработку исключений, например:

try {something} catch (SqlException) {do stuff} catch (Exception) {do other stuff}

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

Традиционная мудрость говорит, что это правильный способ обработки исключений (и что соло Catch (Exception ex) плохо). На практике этот подход не всегда работает, особенно когда вы работаете с компонентами и библиотеками, написанными кем-то другим.

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

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

Ответ 9

Мы используем Catch ex как Exception (вариант VB.Net) совсем немного. Мы регистрируем его и регулярно проверяем наши журналы. Отследите причины и решите.

Я думаю, что Catch ex as Exception полностью согласуется с вашим производственным кодом, и у вас есть общий способ изящно обрабатывать неизвестные исключения. Лично я не ставил общий улов, пока не завершил модуль/новую функциональность и не поставил специализированную обработку для любых исключений, которые я обнаружил при тестировании. Это кажется лучшим из обоих миров.

Ответ 10

Нет; в этом случае, если вы не хотите останавливать программу, вам больше нечего делать, и на верхнем уровне это подходящее место, если вы правильно регистрируетесь и не скрываете ее в надежде усмехаться

Ответ 11

Важно понимать путь исключений через ваше приложение, а не просто бросать или ловить их произвольно. Например, что, если исключение вы поймаете Out-Of-Memory? Вы уверены, что ваше диалоговое окно будет отображаться в этом случае? Но, конечно, прекрасно определить последнюю точку исключения и сказать, что вы никогда не хотите, чтобы ошибки распространялись в прошлом.

Ответ 12

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

И... лучше, чем иметь одну большую попытку поймать, попробовать и поймать, где вам нужен улов.

try {
   myThing.DoStuff();
}
catch (StuffGoneWrongException ex) {
   //figure out what you need to do or bail
}

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

Ответ 13

много раз исключение выделяется на свободные ресурсы, неважно, выбрано ли исключение (re). в этих случаях вы можете избежать try catch:

1) для одноразового объекта вы можете использовать ключевое слово "using":  используя (SqlConnection conn = новое SqlConnection (connStr))  {   // код  } как только вы выйдете из области использования (обычно или с помощью оператора return или путем исключения), метод Dispsose автоматически вызывается на объект. Другими словами, это похоже на попытку/окончательную конструкцию.

2) в asp.net вы можете перехватить событие Error или UnLoad объекта страницы, чтобы освободить ваш ресурс.

Надеюсь, я тебе помогу!

Ответ 14

Я отвечаю на "Однако, остановка процесса - это результат худший...

Если вы можете обрабатывать исключение, запустив другой код (используя try/catch в качестве потока управления), повторите попытку, ожидание и повторите попытку, повторите попытку с помощью другого, но эквивалентного метода (т.е. метода возврата), тем самым сделайте это.

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

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

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

Ответ 15

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

Также помещает это сообщение о подробных деталях в файл журнала.

Ответ 16

Я работаю честно с исключениями, и вот структура реализации, в которой я сейчас следую:

  • Отключить все до ничего /String.Empty/0 и т.д. вне Try/Catch.
  • Инициализировать все внутри Try/Catch для желаемых значений.
  • Сначала выберете наиболее конкретные исключения, например. FormatException, но оставить в базе Обработка исключений в крайнем случае (вы можете иметь несколько блоков catch, помните)
  • Почти всегда исключать исключения
  • Пусть приложение Application_Error в global.asax обрабатывает ошибки изящно, например. вызвать пользовательскую функцию для регистрации сведений об ошибке в файле и перенаправления на страницу с ошибкой
  • Убейте все объекты, которые вы Dimdd в блоке finally

В одном примере, когда я считал приемлемым не обрабатывать исключение, "правильно" недавно работал с строкой GUID (strGuid), переданной через HTTP GET на страницу. Я мог бы реализовать функцию проверки строки GUID для действительности до вызова New Guid (strGuid), но было бы разумно:

Dim myGuid As Guid = Nothing

Try
    myGuid = New Guid(strGuid)
    'Some processing here...

Catch ex As FormatException
    lblError.Text = "Invalid ID"

Catch ex As Exception 
    Throw

Finally
    If myGuid IsNot Nothing Then
        myGuid = Nothing
    End If

End Try