Por que usar finalmente em c #?

187

O que quer que esteja dentro dos blocos finalmente é executado (quase) sempre, então qual é a diferença entre colocar o código nele ou deixá-lo não fechado?

Rodrigo
fonte
3
What do you mean by leaving it unclosed?
Ramesh
5
And what do you mean by "(almost)"?
Beska
49
If you pull the power cord out while a machine is executing a try clause the finally clause will not be called.
Dour High Arch
5
lol, yes, that's true, but you can't really code for that can you?
Ed S.
2
@ Ed: Use transações. Sua cláusula try precisa fazer algum tipo de alteração temporária ou na memória que possa ser persistida em uma única alteração atômica na cláusula finally. Isso raramente é fácil e pode exigir hardware especial.
Dour High Arch

Respostas:

403

The code inside a finally block will get executed regardless of whether or not there is an exception. This comes in very handy when it comes to certain housekeeping functions you need to always run like closing connections.

Now, I'm guessing your question is why you should do this:

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

Quando você pode fazer isso:

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

alwaysDoThis();

A resposta é que, muitas vezes, o código dentro de sua instrução catch repetirá uma exceção ou interromperá a função atual. Com o último código, o "alwaysDoThis ();" chamada não será executada se o código contido na instrução catch emitir um retorno ou lançar uma nova exceção.

Kevin Pang
fonte
3
Hmm. Muito parecido com o que eu disse, mas mais claro e mais exato. +1 definido.
13009 Beska
45
isso se aplica a "return" dentro do bloco try {} também.
Lucas
4
na verdade, aplica-se mesmo sem um bloco catch {} (apenas tentar / finalmente, deixando exceções bolha up)
Lucas
melhor que o meu, estava no trabalho e não queria gastar dez minutos respondendo em detalhes. +1
Matt Briggs
2
Sim, era exatamente isso que eu tinha em mente: D Agora eu entendo.
Rodrigo
62

A maioria das vantagens do uso do try-finalmente já foi apontada, mas pensei em adicionar este:

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).
}

Esse comportamento o torna muito útil em várias situações, principalmente quando você precisa executar uma limpeza (dispor de recursos), embora um bloco de uso geralmente seja melhor nesse caso.

Noldorin
fonte
2
Esta é literalmente a única razão pela qual eu uso finalmente
Christopher Townsend
12

sempre que você usar solicitações de código não gerenciadas, como leitores de fluxo, solicitações de banco de dados, etc; e você deseja capturar a exceção, use try catch finalmente e feche o fluxo, leitor de dados, etc. finalmente, se não o fizer, quando ocorrer um erro, a conexão não será fechada.

 SqlConnection myConn = new SqlConnection("Connectionstring");
        try
        {
            myConn.Open();
            //make na DB Request                
        }
        catch (Exception DBException)
        {
            //do somehting with exception
        }
        finally
        {
           myConn.Close();
           myConn.Dispose();
        }

se você não quiser pegar o erro, use

 using (SqlConnection myConn = new SqlConnection("Connectionstring"))
        {
            myConn.Open();
            //make na DB Request
            myConn.Close();
        }

e o objeto de conexão será descartado automaticamente se houver um erro, mas você não captura o erro

Bob The Janitor
fonte
2
Dispose () também fechará () a conexão, não sendo necessário chamar os dois. Fechar () NÃO Dipose (), você pode reabrir a conexão.
Lucas
Bom, obrigado por mencionar o uso. Eu teria que responder, caso contrário.
Dan Rosenstark 01/08/09
10

Porque finalmente será executado mesmo que você não lide com uma exceção em um bloco de captura.

Matt Briggs
fonte
7

Finalmente, as instruções podem ser executadas mesmo após o retorno.

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
}
Prateek Gupta
fonte
7

finally, como em:

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

is a guaranteed opportunity to execute code after your try..catch block, regardless of whether or not your try block threw an exception.

That makes it perfect for things like releasing resources, db connections, file handles, etc.

David Alpert
fonte
3
All of those examples are typically better served with a using block, but that doesn't really detract from your answer.
Joel Coehoorn
4

eu vou explicar o uso de, finalmente, com uma exceção leitor de arquivos Exemplo

  • sem usar finalmente
try{

  StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
  Console.WriteLine(strReader.ReadeToEnd());
  StreamReader.Close();
}
catch (Exception ex)
{
  Console.WriteLine(ex.Message);
}

no exemplo acima, se o arquivo chamado Data.txt estiver ausente, uma exceção será lançada e será tratada, mas a instrução chamada StreamReader.Close();nunca será executada.
Por esse motivo, os recursos associados ao leitor nunca foram liberados.

  • Para resolver o problema acima, usamos finalmente
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 :)

Nota: "@" é usado para criar uma sequência literal , para evitar o erro de "Sequência de escape não reconhecida". O símbolo @ significa ler essa string literalmente e não interpreta os caracteres de controle de outra maneira.

Ariven Nadar
fonte
2

Digamos que você precise definir o cursor de volta ao ponteiro padrão em vez de um cursor em espera (ampulheta). Se uma exceção for lançada antes de definir o cursor e não travar completamente o aplicativo, você poderá ficar com um cursor confuso.

Chris Doggett
fonte
2

Às vezes, você não deseja manipular uma exceção (sem bloqueio de captura), mas deseja executar algum código de limpeza.

Por exemplo:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}
markom
fonte
Se a exceção não for capturada, a execução do bloco final depende se o sistema operacional escolhe acionar uma operação de desenrolamento de exceção.
Vikas Verma 22/09
2

O bloco final é valioso para limpar todos os recursos alocados no bloco try, além de executar qualquer código que deve ser executado mesmo se houver uma exceção. O controle sempre é passado para o bloco final, independentemente da saída do bloco try.

cgreeno
fonte
1

Ahh...I think I see what you're saying! Took me a sec...you're wondering "why place it in the finally block instead of after the finally block and completely outside the try-catch-finally".

As an example, it might be because you are halting execution if you throw an error, but you still want to clean up resources, such as open files, database connections, etc.

Beska
fonte
1

Control Flow of the Finally Block is either after the Try or Catch block.

[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]

with Exception 1 > 2 > 3 > 4 > 5 if 3 has a Return statement 1 > 2 > 3 > 4

without Exception 1 > 2 > 4 > 5 if 2 has a return statement 1 > 2 > 4

Ranald Fong
fonte
0

As mentioned in the documentation:

A common usage of catch and finally together is to obtain and use resources in a try block, deal with exceptional circumstances in a catch block, and release the resources in the finally block.

It is also worth reading this, which states:

Once a matching catch clause is found, the system prepares to transfer control to the first statement of the catch clause. Before execution of the catch clause begins, the system first executes, in order, any finally clauses that were associated with try statements more nested that than the one that caught the exception.

So it is clear that code which resides in a finally clause will be executed even if a prior catch clause had a return statement.

Nexaspx
fonte