Все, что находится внутри блоков finally, выполняется (почти) всегда, так в чем же разница между заключением в него кода или его закрытием?
Все, что находится внутри блоков finally, выполняется (почти) всегда, так в чем же разница между заключением в него кода или его закрытием?
Ответы:
Код внутри блока finally будет выполнен независимо от того, существует ли исключение. Это очень удобно, когда речь идет о некоторых служебных функциях, которые вы всегда должны запускать как закрытие соединений.
Теперь, я думаю, ваш вопрос, почему вы должны сделать это:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
Когда вы можете сделать это:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
Ответ заключается в том, что код внутри вашего оператора catch часто перебрасывает исключение или прерывает текущую функцию. С последним кодом, "AlwaysDoThis ();" Вызов не будет выполнен, если код внутри оператора catch выдаст возврат или сгенерирует новое исключение.
Большинство преимуществ использования try-finally уже было указано, но я подумал, что добавлю это:
try
{
// Code here that might throw an exception...
if (arbitraryCondition)
{
return true;
}
// Code here that might throw an exception...
}
finally
{
// Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}
Такое поведение делает его очень полезным в различных ситуациях, особенно когда вам необходимо выполнить очистку (утилизировать ресурсы), хотя в этом случае часто лучше использовать блок using .
каждый раз, когда вы используете неуправляемые запросы кода, такие как потоковые считыватели, запросы БД и т. д .; и вы хотите перехватить исключение, затем использовать try catch finally и закрыть поток, считыватель данных и т. д. в finally, если при возникновении ошибок соединение не закрывается, это действительно плохо с запросами базы данных
SqlConnection myConn = new SqlConnection("Connectionstring");
try
{
myConn.Open();
//make na DB Request
}
catch (Exception DBException)
{
//do somehting with exception
}
finally
{
myConn.Close();
myConn.Dispose();
}
если вы не хотите отлавливать ошибку, используйте
using (SqlConnection myConn = new SqlConnection("Connectionstring"))
{
myConn.Open();
//make na DB Request
myConn.Close();
}
и объект подключения будет удален автоматически при возникновении ошибки, но вы не фиксируете ошибку
Потому что, наконец, будет выполняться, даже если вы не обрабатываете исключение в блоке catch.
Наконец, операторы могут выполняться даже после возврата.
private int myfun()
{
int a = 100; //any number
int b = 0;
try
{
a = (5 / b);
return a;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return a;
}
// Response.Write("Statement after return before finally"); -->this will give error "Syntax error, 'try' expected"
finally
{
Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
}
Response.Write("Statement after return after finally"); // -->Unreachable code
}
finally
, как в:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
это гарантированная возможность выполнить код после вашего try..catch
блока, независимо от того, выдал ли ваш блок try исключение.
Это делает его идеальным для таких вещей, как освобождение ресурсов, соединений БД, файловых дескрипторов и т. Д.
Я объясню использование наконец с исключением чтения файлов Пример
try{ StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); StreamReader.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); }
В приведенном выше примере, если файл с именем Data.txt отсутствует, будет сгенерировано исключение, которое будет обработано, но вызываемый операторStreamReader.Close();
никогда не будет выполнен.
Из-за этого ресурсы, связанные с читателем, так и не были выпущены.
StreamReader strReader = null; try{ strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); } catch (Exception ex){ Console.WriteLine(ex.Message); } finally{ if (strReader != null){ StreamReader.Close(); } }
Удачного кодирования :)
Примечание: «@» используется для создания дословной строки, чтобы избежать ошибки «Нераспознанная escape-последовательность». Символ @ означает буквальное прочтение этой строки, иначе не интерпретируйте управляющие символы.
Скажем, вам нужно установить курсор обратно на указатель по умолчанию вместо ожидающего (песочные часы) курсора. Если перед установкой курсора возникает исключение, которое не приводит к аварийному завершению работы приложения, вы можете остаться с запутанным курсором.
Иногда вы не хотите обрабатывать исключение (без блока catch), но хотите, чтобы выполнялся некоторый код очистки.
Например:
try
{
// exception (or not)
}
finally
{
// clean up always
}
Блок finally полезен для очистки любых ресурсов, выделенных в блоке try, а также для запуска любого кода, который должен выполняться, даже если есть исключение. Управление всегда передается блоку finally независимо от выхода из блока try.
Ааа ... Я думаю, я понимаю, что вы говорите! Заняло у меня секунду ... вы задаетесь вопросом "зачем размещать его в блоке finally, а не после блока finally и полностью вне try-catch-finally".
Например, это может быть потому, что вы останавливаете выполнение, если вы выдаваете ошибку, но вы все еще хотите очистить ресурсы, такие как открытые файлы, соединения с базой данных и т. Д.
Поток управления в блоке «В конце» идет после блока «Пробовать» или «Поймать».
[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]
с исключением 1> 2> 3> 4> 5, если 3 имеет оператор Return 1> 2> 3> 4
без исключения 1> 2> 4> 5, если 2 имеет оператор возврата 1> 2> 4
Как указано в документации :
Обычное использование catch и, наконец, вместе - получение и использование ресурсов в блоке try, обработка исключительных обстоятельств в блоке catch и освобождение ресурсов в блоке finally.
Также стоит прочитать это , в котором говорится:
Как только найдено соответствующее предложение catch, система готовится передать управление первому оператору предложения catch. Перед началом выполнения предложения catch система сначала выполняет по порядку все предложения finally, которые были связаны с операторами try, более вложенными, чем те, которые перехватили исключение.
Таким образом, ясно, что код, который находится в finally
предложении, будет выполнен, даже если в предыдущем catch
предложении был return
оператор.