Вопрос

Если отбросить синтаксис, в чем разница между

try {
}
catch() {
}
finally {
    x = 3;
}

и

try {
}
catch() {
}

x = 3;

Редактировать:в .NET 2.0?


итак

try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

эквивалентно ли это с точки зрения поведения?

Это было полезно?

Решение

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

Во втором примере, если код в блоке catch возвращает или завершает работу, x = 3 выполняться не будет.В первом случае так и будет.

В платформе .NET в некоторых случаях выполнение блока finally не произойдет:Исключения безопасности, приостановка потоков, выключение компьютера :) и т.д.

Другие советы

Ну, во-первых, если вы ВЕРНЕТЕСЬ внутрь своего блока try, finally все равно будет выполняться, но код, указанный под блоком try-catch-finally, не будет.

На языке Java:

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

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

Если вы попробуете этот пример:

try {
  return 0;
} finally {
  return 2;
}

Результатом будет 2:)

Сравнение с другими языками: Возвращение Из, Наконец,

Есть несколько вещей, которые делают блок finally полезным:

  1. Если вы возвращаетесь из блоков try или catch, блок finally все еще выполняется, непосредственно перед тем, как управление будет возвращено вызывающей функции
  2. Если в блоке catch возникает исключение или в блоке try возникает исключение неперехваченного типа, код в блоке finally все равно выполняется.

Это делает блоки finally отличными для закрытия дескрипторов файлов или сокетов.

В том случае, если try и catch пусты, разницы нет.В противном случае вы можете быть уверены, что команда finally будет выполнена.

Если вы, например, создадите новое исключение в своем catchblock (rethrow), то назначение будет выполнено только в том случае, если оно находится в finally-блоке.

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

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

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

@Ян и @матс:

Я бы не стал "сносить" что-либо в finally {}, что, как правило, было "настроено" в try {}.Было бы лучше вытащить создание потока за пределы try {}.Если вам нужно обработать исключение при создании потока, это можно было бы сделать в большем масштабе.

StreamReader stream = new StreamReader("foo.bar");  
try {
    mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally {
    stream.close();  
}

Таким образом, вы можете очистить любые открытые соединения и т.д.инициализируется в блоке try.Если вы открыли соединение, а затем возникло исключение, это исключение не было бы закрыто должным образом.Именно для такого сценария и предназначен блок finally.

Предполагается, что блок finally будет выполняться независимо от того, поймали вы исключение или нет.Видишь Пример Try / Catch / Finally

@Эд, возможно , вы думаете о чем - то вроде catch(...) это улавливает неуказанное исключение в C ++.

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

У Корпорации Майкрософт есть страница справки по попробуйте-наконец-то для C#

Блок finally находится в той же области видимости, что и try / catch, поэтому у вас будет доступ ко всем переменным, определенным внутри.

Представьте, что у вас есть обработчик файлов, вот в чем разница в том, как он будет написан.

try
{
   StreamReader stream = new StreamReader("foo.bar");
   stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
   stream.close();
}

по сравнению с

StreamReader stream = null;
try
{
    stream = new StreamReader("foo.bar");
    stream.write("foo");
} catch(Exception e) {} // ignore

if (stream != null)
    stream.close();

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

Любой код в finally выполняется в the даже в случае необработанного исключения.Обычно код finally используется для очистки локальных объявлений неуправляемого кода с помощью .dispose().

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

@mats очень корректен в том, что всегда существует вероятность "жестких" сбоев - блоки finally не должны включать критически важный код, который всегда должен выполняться транзакционно внутри try {}

@mats again - настоящая прелесть в том, что это позволяет вам возвращать исключения из ваших собственных методов и при этом гарантировать, что вы приведете их в порядок:

try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally
{
stream.close();
}

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

В Java вы используете его для всего, что хотите выполнить, независимо от того, использовали ли вы "return", просто выполнили блок try или перехватили исключение.

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

Я предполагаю, что это похоже на .NET?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top