Есть ли польза от ТОЛЬКО броска при ловле?

У меня были "горячие споры" с коллегой по поводу его практики обертывания большинства своих функций в try / catch, но уловка имеет ТОЛЬКО "бросок", например

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

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

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

Хорошо, что может быть полезно в режиме отладки, чтобы не всплывать внезапно родительскому члену (да, Джоэл!) - вы перейдете к оператору throw и сможете проверить свои локальные переменные. Но тогда ваш код будет «завален попытками / уловами / выбросами» (цитирую здесь другой тред)?

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


person AndrewD    schedule 20.10.2008    source источник
comment
Отсортируйте свой код VB, это выглядит ужасно.   -  person Rob Stevenson-Leggett    schedule 20.10.2008
comment
Попробуйте печатать одной рукой и извивающимся ребенком в 23:00! 80/20 - делает свое дело.   -  person AndrewD    schedule 21.10.2008
comment
Никакого упоминания о преимуществах многопоточности - могу ли я предположить, что тогда это не актуально?   -  person AndrewD    schedule 21.10.2008
comment
И я предполагаю, что MSIL вставит хотя бы одну или две строки для попытки / улова (MSIL для меня греческий язык), поэтому общее мнение о том, что этого не делать, является разумным.   -  person AndrewD    schedule 21.10.2008
comment
Спасибо всем - кажется, что это не лучший вариант, и Ctrl + Alt + E Джона, чтобы сломать все, - правильная (не уверенная в лучшей) альтернатива. Все еще интересуюсь битом многопоточности ... но все это соответствует обычным практикам std.   -  person AndrewD    schedule 21.10.2008
comment
Вы должны более четко указать на проблему с многопоточностью. Мне не известны проблемы с отладкой многопоточных приложений с помощью Visual Studio. Кроме того, для меня отлично работает нарушение исключения исключений.   -  person Jan    schedule 21.10.2008
comment
Небольшая вещь, которую я обнаружил недавно с помощью throw & throw ex - номер строки, указанный в трассировке, будет номером строки throw! Единственный способ получить правильную строку # - это создать новое исключение (например, сообщение, например). Подробнее см. stackoverflow.com/questions/2493779/   -  person AndrewD    schedule 12.04.2021


Ответы (10)


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

person Joel Coehoorn    schedule 20.10.2008
comment
Еще одна причина для повторного выброса - очистить существующее состояние - это все равно что сказать: «Хорошо, я знаю, что случилось что-то плохое». Я не могу с этим справиться, но я уберу, прежде чем передать это кому-то другому. Иногда, наконец, это НЕ подходящее место для этого. - person plinth; 20.10.2008
comment
В то время как одиночный бросок сохранит состояние, поэтому исключение не будет обнаружено. Если вы хотите установить точку останова для отладки, установите точку останова в разделе Отладка ›Исключения. Оговорка о перехвате совершенно не нужна. - person Dour High Arch; 21.10.2008
comment
@DHA: Объясните, пожалуйста, как вы поймаете исключение на определенном уровне в стеке вызовов, глубина которого может быть 20 уровней. - person Jon Skeet; 21.10.2008
comment
Он означает, что вы должны включить автоматические прерывания при любом возникновении данного исключения, которое вы можете включить в меню ›отладки исключений. - person Jan; 21.10.2008
comment
Вы можете сломаться, когда его бросили, но тогда может быть больно вернуть стопку на нужную сумму. Я не говорю, что это обычное дело, но такое случается. - person Jon Skeet; 21.10.2008
comment
(А еще одно и то же исключение может быть выброшено из многих других мест.) - person Jon Skeet; 21.10.2008

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

Так что, как правило, не рекомендуется ловить и повторно генерировать исключение.

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

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

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

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

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

person Jan    schedule 20.10.2008
comment
Спасибо за подсказку Ctrl + Alt + e (хотя вам нужна активная панель кода) ... не могу найти ее в системе главного меню (я бы ожидал, что это будет в меню Инструменты- ›Параметры ... Отладка). - person AndrewD; 21.10.2008
comment
Обычно вы найдете его в меню «Отладка» - ›Исключения, когда проект загружен и окно кода активно. - person Jan; 21.10.2008
comment
В VS2005 этого, похоже, нет ... но есть Ctrl + Alt + E !? Необходимо обновить :-( - person AndrewD; 21.10.2008
comment
Не могу вам сказать, потому что я деинсталлировал VS2005 :) - person Jan; 22.10.2008

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

person Jon Skeet    schedule 20.10.2008
comment
По умолчанию точно так не пишите. Но если мне нужно добавить это во время сеанса отладки, я бы, вероятно, оставил его. Если бы он мне понадобился один раз, я, вероятно, сделаю это снова, и это тонкий способ сообщить другим разработчикам, что включенный код может быть сложнее, чем кажется . - person Joel Coehoorn; 20.10.2008
comment
Тогда я бы добавил это в комментарий, вместо того, чтобы оставлять уродливый и отвлекающий код. В большинстве случаев, когда этот код необходимо прочитать, вероятно, не будет такая же ситуация, поэтому не усложняйте ее для этого случая. - person Jon Skeet; 20.10.2008
comment
Я не думаю, что стоит что-то тестировать, а затем изменять код перед проверкой. - person Dour High Arch; 21.10.2008
comment
Я бы не стал делать это просто перед регистрацией. Я бы использовал отладчик, чтобы выяснить, что идет не так; напишите неудачный модульный тест; уберите попытку / поймать / бросить и доказать, что все еще идет не так; исправить это и увидеть, как все станет зеленым; отправить на проверку кода; отметиться. Вы никогда ничего не удаляете из кода? - person Jon Skeet; 21.10.2008
comment
Мужик по сердцу, Мрачная Высокая Арка! Биться об этом с молодым человеком ... любые изменения - это новый риск !! Условные ЕСЛИ я считаю полезными, но не менее опасными. - person AndrewD; 21.10.2008

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

person Geoff    schedule 20.10.2008

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

person Fabian Buch    schedule 20.10.2008
comment
Если вы выбрасываете другое исключение, это не ситуация, описанная OP. Он конкретно говорит о ситуации с голым броском. - person Jon Skeet; 20.10.2008
comment
Тогда я не знаю причины, так как для отладки есть отладчики. - person Fabian Buch; 20.10.2008

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

person Dour High Arch    schedule 20.10.2008
comment
Однако это не поможет вам поймать их на определенном уровне стека, что часто бывает удобно. - person Jon Skeet; 21.10.2008

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

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

person Neil    schedule 20.10.2008

Да, это удобно для того, чтобы поставить точку останова в уловке.

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

person Mark Ransom    schedule 20.10.2008

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

person Bryan    schedule 20.10.2008

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

person DCNYAM    schedule 22.10.2008