Разница между try / catch / throw и try / catch (e) / throw e

В чем разница между

try { } catch { throw; } 

а также

 try { } catch(Exception e) { throw e;} 

?

И когда я должен использовать тот или иной?

Конструкции

 try { ... } catch () { ... } /* You can even omit the () here */ try { ... } catch (Exception e) { ... } 

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

 try { ... } catch () { /* ... */ throw; } try { ... } catch (Exception e) { /* ... */ throw; } try { ... } catch (Exception e) { /* ... */ throw e; } 

Первый и второй блоки try-catch ТОЧНО одно и то же, они просто реконструируют текущее исключение, и это исключение сохранит его «источник» и трассировку стека.

Третий блок try-catch отличается. Когда он выдает исключение, он изменит трассировку источника и стека, так что будет казаться, что исключение было выбрано из этого метода, из той самой строки, которая throw e метод, содержащий этот блок try-catch.

Какой из них вы должны использовать? Это действительно зависит от каждого случая.

Допустим, у вас есть class Person с .Save() который будет сохраняться в базе данных. Предположим, что ваше приложение Person.Save() то образом выполняет метод Person.Save() . Если ваша БД отказывается сохранять Личность, то .Save() исключение. Должны ли вы использовать throw или throw e в этом случае? Смотря как.

Я предпочитаю делать:

 try { /* ... */ person.Save(); } catch(DBException e) { throw new InvalidPersonException( "The person has an invalid state and could not be saved!", e); } 

Это должно поместить DBException как «Внутреннее исключение» для нового исключения. Поэтому, когда вы проверяете это InvalidPersonException, трассировка стека будет содержать информацию обратно к методу Save (этого может быть достаточно для решения проблемы), но вы все равно имеете доступ к исходному исключению, если вам это нужно.

В качестве заключительного замечания, когда вы ожидаете исключения, вы должны действительно поймать это конкретное исключение, а не общее Exception , то есть, если вы ожидаете InvalidPersonException, вы должны предпочесть:

 try { ... } catch (InvalidPersonException e) { ... } 

в

 try { ... } catch (Exception e) { ... } 

Удачи!

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

Второй подход может быть полезен, если вы хотите добавить дополнительную информацию в трассировку стека, но она используется следующим образом:

 try { // do something } catch (Exception ex) { throw new Exception("Additional information...", ex); } 

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

Вы должны использовать

 try { } catch(Exception e) { throw } 

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

Разница между беззаметным уловом и catch(Exception e) заключается в том, что вы получаете ссылку на исключение. Из фреймворка версии 2 неуправляемые исключения обернуты в управляемое исключение, поэтому исключение без параметров не более полезно ни для чего.

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

Таким образом, вы не использовали ни один из альтернатив в вопросе. Вы не должны использовать захват без параметров, и вы должны использовать throw; для отмены исключения.

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

 try { ... } catch (IOException e) { ... throw; } 

Если вы хотите добавить какую-либо информацию при повторном создании исключения, вы создаете новое исключение с исходным исключением как внутреннее исключение для хранения всей информации:

 try { ... } catch (IOException e) { ... throw new ApplicationException("Some informative error message", e); } 
  • Исключение исключения: деление на ноль
  • Node.js Обработка исключений при передовом опыте
  • Должны ли вы сообщать текст сообщений об исключениях?
  • CompletedFuture уже завершен с исключением
  • Обработка исключений - это хороший способ?
  • Когда я должен действительно использовать noexcept?
  • Что на самом деле происходит в try {return x; } наконец {x = null; } заявление?
  • Лучшая практика для обработки исключений в приложении Windows Forms?
  • Как вы обрабатываете ресурсы в MATLAB безопасным образом? (например, «попробуй ... наконец»)
  • VS2010 не показывает необработанное сообщение об исключении в приложении WinForms в 64-разрядной версии Windows
  • Блоки catch C ++ - исключение catch по значению или ссылке?
  • Давайте будем гением компьютера.