Что бы ни было внутри, наконец, блоки выполняются (почти) всегда, так какая разница между вложением в него кода или его закрытием?
Зачем использовать в С#?
Ответ 1
Код внутри блока finally будет выполняться независимо от того, существует или нет исключение. Это очень удобно, когда речь идет о некоторых функциях домоуправления, которые вам нужно всегда запускать, как закрывающие соединения.
Теперь, я предполагаю, что ваш вопрос заключается в том, почему вы должны это сделать:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
Когда вы можете сделать это:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
Ответ заключается в том, что много раз код внутри вашего оператора catch будет либо отменять исключение, либо выходить из текущей функции. С последним кодом "alwaysDoThis();" вызов не будет выполняться, если код внутри оператора catch вызывает возврат или генерирует новое исключение.
Ответ 2
Большинство преимуществ использования 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).
}
Такое поведение делает его очень полезным в различных ситуациях, особенно когда вам нужно выполнить очистку (распоряжаться ресурсами), хотя в этом случае часто используется блок-блок.
Ответ 3
в любое время, когда вы используете неуправляемые запросы кода, такие как считыватели потоков, запросы db и т.д.; и вы хотите поймать исключение, тогда используйте try catch окончательно и закройте поток, считыватель данных и т.д., в конце концов, если вы этого не сделаете, когда ошибки не закрываются, это действительно плохо с db-запросами
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();
}
и объект соединения будет удален автоматически, если есть ошибка, но вы не зафиксируете ошибку
Ответ 4
Потому что, наконец, он будет выполнен, даже если вы не обрабатываете исключение в блоке catch.
Ответ 5
finally
, как в:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
- это гарантированная возможность выполнить код после блока try..catch
, независимо от того, выбрал ли ваш блок try исключение.
Это делает его идеальным для таких вещей, как освобождение ресурсов, db-соединений, файлов и т.д.
Ответ 6
Наконец, операторы могут выполняться даже после возврата.
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
}
Ответ 7
я объясню использование окончательно с исключением чтения файла Пример
- без использования наконец
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(); } }
Счастливое кодирование:)
Примечание: "@" используется для создания строки verbatim, чтобы избежать ошибки "Unrecognized escape sequence". Символ @означает чтение этой строки в буквальном смысле и не интерпретировать контрольные символы иначе.
Ответ 8
Скажем, вам нужно установить курсор на указатель по умолчанию вместо курсора ожидания (песочные часы). Если перед настройкой курсора выбрано исключение, и он не нарушает приложение, вы можете оставить его с запутанным курсором.
Ответ 9
Блок finally полезен для очистки любых ресурсов, выделенных в блоке try, а также для запуска любого кода, который должен выполняться, даже если является исключением. Контроль всегда передается блоку finally независимо от того, как выйдет блок try.
Ответ 10
Иногда вы не хотите обрабатывать исключение (без блока catch), но вы хотите, чтобы какой-то код очистки выполнялся.
Например:
try
{
// exception (or not)
}
finally
{
// clean up always
}
Ответ 11
Используя блок finally
, вы можете очистить все ресурсы, выделенные в блоке try
, и вы можете запускать код, даже если в блоке try
возникает исключение. Как правило, инструкции блока finally
запускаются, когда элемент управления оставляет оператор try. Передача управления может произойти в результате нормального выполнения, выполнения инструкции break, continue, goto, or return
или распространения исключения из инструкции try
.
В обработанном исключении гарантируется, что соответствующий блок finally
будет запущен. Однако, если исключение необработанно, выполнение блока finally
зависит от того, как запускается операция исключения разрыва. Это, в свою очередь, зависит от того, как настроен ваш компьютер. Для получения дополнительной информации см. Обработка необработанных исключений в среде CLR.
Обычно, когда необработанное исключение завершает приложение, независимо от того, выполняется ли блок finally
, не важно. Однако, если у вас есть инструкции в блоке finally
, который должен быть запущен даже в этой ситуации, одним из решений является добавление блока catch
в оператор try-finally
. Кроме того, вы можете поймать исключение, которое может быть выбрано в блоке try
оператора try-finally
выше стека вызовов. То есть вы можете поймать исключение в методе, который вызывает метод, содержащий оператор try-finally
, или метод, вызывающий этот метод, или любым способом в стеке вызовов. Если исключение не было обнаружено, выполнение блока finally
зависит от того, решит ли операционная система инициировать операцию отключения исключения.
public class ThrowTestA
{
static void Main()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// To run the program in Visual Studio, type CTRL+F5. Then
// click Cancel in the error dialog.
Console.WriteLine("\nExecution of the finally block after an unhandled\n" +
"error depends on how the exception unwind operation is triggered.");
Console.WriteLine("i = {0}", i);
}
}
// Output:
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
//
// Execution of the finally block after an unhandled
// error depends on how the exception unwind operation is triggered.
// i = 123
}
В следующем примере исключение из метода TryCast поймано в методе, находящемся выше стека вызовов. С#
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
Ответ 12
Ах... Думаю, я понимаю, о чем ты говоришь! Взял меня в сек... вы задаетесь вопросом: "Зачем ставить его в блок finally, а не после блока finally и полностью за пределами try-catch-finally".
В качестве примера может случиться так, что вы прекратите выполнение, если вы выбросите ошибку, но вы все равно хотите очистить ресурсы, такие как открытые файлы, подключения к базам данных и т.д.
Ответ 13
Управление потоком блока finally выполняется либо после блока Try, либо Catch.
[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
Ответ 14
Наконец блок
Если у вас есть одно или несколько операторов, которые должны выполняться до выхода из структуры Try
, используйте блок Finally
. Блок Finally
полезен для запуска любого кода, который должен выполняться, даже если есть исключение. Управление передается блоку Finally
независимо от того, как выйдет блок Try
... Catch
. Управление переходит к блоку Finally
непосредственно перед тем, как он выходит из структуры Try
... Catch
. Это верно, даже если исключение встречается где угодно внутри структуры Try
. Код в блоке Finally
выполняется, даже если ваш код встречает оператор Return
в блоке Try
или Catch
.
Неправильно передать выполнение в блок Finally
.
Передача выполнения из блока Finally
недопустима, за исключением исключения.
Ответ 15
Как указано в документации:
Обычное использование catch и, наконец, вместе - получение и использование ресурсов в блоке try, обработка исключительных обстоятельств в блоке catch и освобождение ресурсов в блоке finally.
Также стоит прочитать этот, в котором говорится:
Как только найдено соответствующее предложение catch, система готовится передать управление первому оператору предложения catch. Перед началом выполнения предложения catch система сначала выполняет по порядку все предложения finally, связанные с операторами try, более вложенными, чем те, которые перехватили исключение.
Таким образом, ясно, что код, который находится в предложении finally
, будет выполнен, даже если в предыдущем предложении catch
был оператор return
.