Зачем использовать наконец в C #? - PullRequest
174 голосов
/ 14 февраля 2009

Все, что находится внутри блоков finally, выполняется (почти) всегда, так в чем же разница между встраиванием в него кода или его закрытием?

Ответы [ 14 ]

375 голосов
/ 14 февраля 2009

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

Теперь я догадываюсь ваш вопрос, почему вы должны сделать это:

try
{
    doSomething();
}
catch
{
    catchSomething();
}
finally
{
    alwaysDoThis();
}

Когда вы можете сделать это:

try
{
    doSomething();
}
catch
{
    catchSomething();
}

alwaysDoThis();

Ответ заключается в том, что код внутри вашего оператора catch много раз перебрасывает исключение или прерывает текущую функцию. С последним кодом, "AlwaysDoThis ();" Вызов не будет выполнен, если код внутри оператора catch выдает возврат или выдает новое исключение.

57 голосов
/ 14 февраля 2009

Большинство преимуществ использования 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).
}

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

11 голосов
/ 14 февраля 2009

каждый раз, когда вы используете неуправляемые запросы кода, такие как потоковые считыватели, запросы БД и т. Д .; и вы хотите перехватить исключение, затем использовать try catch finally и закрыть поток, считыватель данных и т. д. в finally, если вы не ошибетесь, соединение не закрывается, это действительно плохо с запросами базы данных 1001 *

 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();
        }

и объект подключения будет удален автоматически при возникновении ошибки, но вы не фиксируете ошибку

10 голосов
/ 14 февраля 2009

Потому что, наконец, будет выполнено, даже если вы не обработаете исключение в блоке catch.

7 голосов
/ 05 августа 2013

Наконец, операторы могут выполняться даже после возврата.

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 голосов
/ 14 февраля 2009

finally, как в:

try {
  // do something risky
} catch (Exception ex) {
  // handle an exception
} finally {
  // do any required cleanup
}

- это гарантированная возможность выполнения кода после вашего блока try..catch, независимо от того, выдал ли ваш блок try исключение.

Это делает его идеальным для таких вещей, как освобождение ресурсов, соединений БД, файловых дескрипторов и т. Д.

3 голосов
/ 11 декабря 2017

я объясню использование finally с исключением для чтения файлов Пример

  • без использования наконец
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(); никогда не будет казнен.
Из-за этого ресурсы, связанные с читателем, никогда не выпускались.

  • Чтобы решить вышеуказанную проблему, мы используем finally
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();
    }
}

Happy Coding:)

Примечание: «@» используется для создания дословной строки, чтобы избежать ошибки «Нераспознанная escape-последовательность». Символ @ означает буквальное прочтение этой строки, иначе не интерпретируйте управляющие символы.

3 голосов
/ 03 января 2015

Используя блок 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 перехватывается в методе, расположенном дальше по стеку вызовов. C #

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.
}
2 голосов
/ 14 февраля 2009

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

Например:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}
2 голосов
/ 14 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...