Различие между попыткой/выгодой/броском и попыткой/выгодой (e) / бросает e

Также существует другой выбор языка. Я стал довольно любящим Python, который работает хорошо над Windows, Linux и Mac, и имеет богатый набор библиотек.

101
задан Peter Mortensen 9 June 2014 в 15:50
поделиться

4 ответа

Конструкции

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 - ТОЧНО одно и то же, они просто повторно генерируют текущее исключение, и это исключение сохранит свой «источник» и трассировку стека.

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

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

Пусть ' s скажем, у вас есть класс 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 (этого может быть достаточно для решения проблемы), но у вас все еще есть доступ к исходному исключению, если оно вам нужно.

последнее замечание: когда вы ожидаете исключения,

147
ответ дан 24 November 2019 в 04:41
поделиться

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

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

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

В блоге сообщение обсуждает различия.

32
ответ дан 24 November 2019 в 04:41
поделиться

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

try { }
catch(Exception e)
{ throw }

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

6
ответ дан 24 November 2019 в 04:41
поделиться

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

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

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

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

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

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

try {
   ...
} catch (IOException e) {
   ...
   throw new ApplicationException("Some informative error message", e);
}
5
ответ дан 24 November 2019 в 04:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: