Perché usiamo finalmente i blocchi?


91

Per quanto ne so, entrambi i seguenti frammenti di codice avranno lo stesso scopo. Perché hanno i finallyblocchi?

Codice A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

Codice B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

Questo non è specifico per C #, è una domanda .Net
Sruly

1
Non più necessario con java7: AutomaticResourceManagement, prova (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Risposte:


139
  • Cosa succede se viene generata un'eccezione che non stai gestendo? (Spero che tu non stia prendendo Throwable...)
  • Cosa succede se torni dall'interno del blocco try?
  • Cosa succede se il blocco catch genera un'eccezione?

Un finallyblocco si assicura che comunque si esce da quel blocco (modulo alcuni modi per interrompere esplicitamente l'intero processo), verrà eseguito. È importante per la pulizia deterministica delle risorse.


48
Non necessariamente vero; alla fine non verrà eseguito se (1) c'è una System.exit()chiamata (2) c'è un loop infinito nel try o uno dei blocchi catch (3)
Stacco

2
@Alon prova {return 1; } finalmente {retrun 2; } Riceverai 2
Dennis C

19
@NullUserException: da qui il bit "modulo a pochi modi ..."
Jon Skeet

2
John Skeet vive qui su StackOverflow, ogni domanda è come un campanello a cui deve rispondere :)
naikus

1
Questo post discute le (rare) condizioni in cui alla fine NON sarà chiamato.
Candamir

13

Nota che (almeno in Java, probabilmente anche in C #) è anche possibile avere un tryblocco senza un catch, ma con un finally. Quando si verifica un'eccezione nel tryblocco, il codice nel finallyblocco viene eseguito prima che l'eccezione venga lanciata più in alto:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

7

Potresti voler mettere il codice che vuoi che venga comunque eseguito indipendentemente da ciò che accade nel tuo blocco try or catch.

Inoltre, se stai usando più catch e se vuoi mettere del codice comune a tutti i blocchi catch, questo sarebbe un posto dove metterlo, ma non puoi essere sicuro che l'intero codice in try sia stato eseguito.

Per esempio:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}

1
E se non utilizzo "finalmente" ma chiudo la connessione?
Istiaque Ahmed

5

Alla fine viene sempre eseguito, mentre il tuo codice dopo la cattura potrebbe non farlo.


1
perchè no! Se l'eccezione viene gestita correttamente, il codice verrà eseguito definitivamente.
Mohammad Nadeem

1
@Nadeem: vedi la mia risposta per 3 motivi che potrebbe non accadere.
Jon Skeet

2

Anche se la nostra applicazione è chiusa forzatamente, ci saranno alcune attività che dobbiamo eseguire (come il rilascio della memoria, la chiusura del database, il blocco del rilascio, ecc.), Se scrivi queste righe di codice nel finallyblocco, verrà eseguito se viene generata un'eccezione o non...

La tua applicazione può essere una raccolta di thread, Exceptiontermina il thread ma non l'intera applicazione, in questo caso finallyè più utile.

In alcuni casi finallynon verrà eseguito come JVM Fail, Thread terminate, ecc.


1

Perché è necessario che il codice venga eseguito indipendentemente da eventuali eccezioni che potrebbero essere generate. Ad esempio, potrebbe essere necessario ripulire alcune risorse non gestite (il costrutto "using" viene compilato in un blocco try / latest).


0

Ci possono essere momenti in cui vuoi eseguire un pezzo di codice, non importa cosa. Indica se viene generata un'eccezione o meno. Quindi si usa finally.


0

finallySEMPRE viene eseguito, a meno che la JVM non sia stata chiusa, finallyfornisce solo un metodo per mettere il codice di pulizia in un unico posto.

Sarebbe troppo noioso se dovessi inserire il codice di pulizia in ciascuno dei catchblocchi.


0

Se il blocco catch genera un'eccezione, il codice rimanente non verrà eseguito, quindi dobbiamo scrivere il blocco finale.


0

infine il blocco in java può essere utilizzato per inserire il codice di "pulizia" come la chiusura di un file, la chiusura della connessione ecc.


Il blocco finalmente non verrà eseguito se il programma esce (chiamando System.exit () o causando un errore fatale che causa l'interruzione del processo).


0

Stai ancora scorrendo verso il basso? Ecco qui!

Questa domanda mi ha fatto tornare indietro un po 'di tempo.

try
{
 int a=1;
 int b=0;
 int c=a/b;
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}
finally
{
 console.writeline("Finally block");
}
console.writeline("After finally");

cosa verrebbe stampato nello scenario precedente? Sì, hai indovinato:

  • es. messaggio - qualunque cosa sia (probabilmente si è tentata una divisione per zero)

  • Infine blocca

  • Dopo finalmente

    try
    {
        int a=1;
        int b=0;
        int c=a/b;
    }
    catch(Exception ex)
    {
        throw(ex);
    }
    finally
    {
        console.writeline("Finally block");
    }
    console.writeline("After finally");
    

Cosa sarebbe questa stampa? Niente! Genera un errore poiché il blocco catch ha generato un errore.

In una buona struttura di programmazione, le tue eccezioni sarebbero incanalate, nel senso che questo codice verrà gestito da un altro livello. Per stimolare un caso del genere, cercherò di annidare questo codice.

try
{    
 try
    {
     int a=1;
     int b=0;
     int c=a/b;
    }
    catch(Exception ex)
    {
     throw(ex);
    }
    finally
    {
     console.writeline("Finally block")
    }
    console.writeline("After finally");
}
catch(Exception ex)
{
 console.writeline(ex.Message);
}

In questo caso l'output sarebbe:

  • Infine blocca
  • es. messaggio, qualunque esso sia.

È chiaro che quando si cattura un'eccezione e la si lancia di nuovo in altri livelli (Funneling), il codice dopo il lancio non viene eseguito. Agisce in modo simile a come funziona un ritorno all'interno di una funzione.

Ora sai perché non chiudere le tue risorse sui codici dopo il blocco catch, inserendole infine nel blocco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.