Есть ли какая-то польза от "броска" в уловке?

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

Private sub foo()
    try
        'Do something'
    catch
        throw 'And nothing else!'
    End Try
End Sub

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

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

Хорошо, что может быть полезно в режиме отладки не внезапно выскочить к родительскому члену (да, Joel!) - вы перейдете в инструкцию "throw" и сможете исследовать своих локальных жителей. Но тогда ваш код будет "замусорен с помощью try/catch/throws" (чтобы процитировать здесь еще один поток)?

И какие бы накладные расходы были связаны с добавлением try/catch/throws во всех случаях, если не возникает исключение (например, если вы избегаете попыток/улов в жестких циклах)?

Ответы

Ответ 1

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

Ответ 2

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

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

Причины ловить и заменить его другим исключением могут быть

  • Вход
  • Скрытие конфиденциальной информации от вызывающего (Stacktrace, сведения об исключении)

И для отладки вы можете захотеть изменить свой "разрыв, когда исключение:" - обработчик (нажмите Ctrl + Alt + e) ​​значение "брошено" на выбранные исключения CLR.

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

Один из последствий использования улова и немедленного восстановления - это то, что любые внутренние "окончательные" блоки будут выполняться до появления "Catch" (что, в свою очередь, будет до распространения исключения). Это актуально в двух сценариях:

  • Если исключение в конечном счете необработано, возможно, что ловушка необработанного исключения может выйти из приложения без каких-либо "окончательных" блоков. Выполнение улова и немедленное ретронирование гарантируют, что все "окончательные" блоки в улове будут выполняться, даже если исключение в конечном итоге будет необработанным.
  • Возможно, код на vb.net и, возможно, на других языках, будет действовать на исключение, прежде чем будут запущены какие-либо окончательные блоки. Использование блока "try" с catch-and-instant-rethrow приведет к тому, что блоки "finally" в этом блоке catch будут выполняться до того, как любые внешние блоки "try" получат первый взгляд на исключение.

Дополнительная оговорка с уловкой и немедленным восстановлением: по какой-то причине улов и немедленный ретроуз приведет к удалению номера строки трассировки стека для вызова функции, вызвавшего исключение. Я не знаю, почему в этом случае текущая запись функции в трассировке стека не может быть оставлена ​​в одиночестве, но это не так. Если вы не используете файл .pdb для получения информации о номере линии, это не проблема, но если вы хотите использовать такую ​​информацию, это может раздражать.

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

Ответ 6

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

Ответ 7

Да, это удобно для установки точки останова в catch.

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

Ответ 8

Вам нужно not использовать предложение catch для исключения исключений в отладчике Visual Studio. Выберите Debug > Исключения и выберите, какие исключения вы хотите уловить, при необходимости все они.

Ответ 9

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

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

Ответ 10

Поскольку обработка ошибок равна нулю, этот улов бесполезен. Если бы была регистрация или какая-то очистка, конечно, но в этой ситуации я бы избавился от try/catch.

Ответ 11

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