Perché usare finalmente in C #?


189

Qualunque cosa sia dentro, infine, i blocchi vengono eseguiti (quasi) sempre, quindi qual è la differenza tra racchiudere il codice o lasciarlo chiuso?


3
Che cosa vuoi dire lasciandolo chiuso?
Ramesh,

5
E cosa intendi con "(quasi)"?
Beska,

49
Se si estrae il cavo di alimentazione mentre una macchina sta eseguendo una clausola try, la clausola finally non verrà chiamata.
Dour High Arch,

5
lol, sì, è vero, ma non puoi davvero programmare per quello, vero?
Ed S.,

2
@Ed: usa le transazioni. La clausola try deve apportare una sorta di modifica temporanea o in memoria che può essere mantenuta in una singola modifica atomica nella clausola finally. Raramente è facile e può richiedere hardware speciale.
Dour High Arch,

Risposte:


405

Il codice all'interno di un blocco finally verrà eseguito indipendentemente dal fatto che esista o meno un'eccezione. Questo è molto utile quando si tratta di alcune funzioni di pulizia che è necessario eseguire sempre come connessioni di chiusura.

Ora, immagino che la tua domanda sia: perché dovresti farlo:

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

Quando puoi farlo:

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

alwaysDoThis();

La risposta è che molte volte il codice all'interno della tua dichiarazione catch rileggerà un'eccezione o uscirà dalla funzione corrente. Con quest'ultimo codice, "alwaysDoThis ();" la chiamata non verrà eseguita se il codice all'interno dell'istruzione catch genera un ritorno o genera una nuova eccezione.


3
Hmm. Molto simile a quello che ho detto, ma più chiaro e più esatto. +1 preciso.
Beska,

46
questo vale anche per "return" all'interno del blocco try {}.
Lucas,

4
in effetti, si applica anche senza un blocco catch {} (basta provare / finalmente, facendo scoppiare le eccezioni)
Lucas,

meglio del mio, era al lavoro e non volevo passare dieci minuti a rispondere nel dettaglio. +1
Matt Briggs,

2
Sì, questo era esattamente quello che avevo in mente: D Ora lo capisco.
Rodrigo,

62

La maggior parte dei vantaggi dell'utilizzo di try-finally sono già stati evidenziati, ma ho pensato di aggiungere questo:

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

Questo comportamento lo rende molto utile in varie situazioni, in particolare quando è necessario eseguire la pulizia (disporre delle risorse), anche se un utilizzo in questo caso blocco sia spesso migliore.


2
Questa è letteralmente l'unica ragione per cui finalmente uso
Christopher Townsend il

12

ogni volta che usi richieste di codice non gestito come lettori di stream, richieste di db, ecc .; e vuoi catturare l'eccezione, quindi usa prova infine a catturare e chiudi il flusso, il lettore di dati, ecc. infine, se non lo fai quando si verifica un errore la connessione non viene chiusa, questo è davvero male con le richieste 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();
        }

se non si desidera rilevare l'errore, utilizzare

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

e l'oggetto connessione verrà eliminato automaticamente in caso di errore, ma non si acquisisce l'errore


2
Dispose () chiuderà anche () la connessione, non è necessario chiamare entrambi. Close () NON Dipose (), è possibile riaprire la connessione.
Lucas,

Bello, grazie per aver menzionato l'utilizzo. Dovrei rispondere, altrimenti.
Dan Rosenstark,

11

Perché finalmente verrà eseguito anche se non si gestisce un'eccezione in un blocco catch.


7

Infine, le istruzioni possono essere eseguite anche dopo il ritorno.

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

finally, come in:

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

è un'opportunità garantita per eseguire il codice dopo il tuo try..catch blocco, indipendentemente dal fatto che il blocco try abbia o meno generato un'eccezione.

Questo lo rende perfetto per cose come il rilascio di risorse, connessioni db, handle di file, ecc.


3
Tutti questi esempi sono generalmente meglio serviti con un blocco using, ma ciò non toglie davvero la tua risposta.
Joel Coehoorn,

4

spiegherò l'uso di finalmente con un esempio di eccezione del lettore di file

  • senza usare finalmente
try{

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

nell'esempio precedente se manca il file chiamato Data.txt , verrà generata un'eccezione che verrà gestita ma l' istruzione chiamata StreamReader.Close();non verrà mai eseguita.
A causa di queste risorse associate al lettore non è mai stato rilasciato.

  • Per risolvere il problema sopra, usiamo 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: "@" viene utilizzato per creare una stringa testuale , per evitare errori di "Sequenza di escape non riconosciuta". Il simbolo @ significa leggere quella stringa letteralmente e non interpretare altrimenti i caratteri di controllo.


2

Supponiamo che sia necessario reimpostare il cursore sul puntatore predefinito anziché su un cursore di attesa (clessidra). Se viene generata un'eccezione prima di impostare il cursore e non si blocca completamente l'app, potresti rimanere con un cursore confuso.


2

A volte non si desidera gestire un'eccezione (nessun blocco catch), ma si desidera eseguire un codice di cleanup.

Per esempio:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}

Se l'eccezione non viene rilevata, l'esecuzione del blocco finally dipende dal fatto che il sistema operativo scelga di attivare un'operazione di svolgimento dell'eccezione.
Vikas Verma,

2

Il blocco finally è utile per ripulire tutte le risorse allocate nel blocco try e per eseguire qualsiasi codice che deve essere eseguito anche in presenza di un'eccezione. Il controllo viene sempre passato al blocco finally indipendentemente da come esce il blocco try.


1

Ahh ... penso di vedere quello che stai dicendo! Mi ci è voluto un secondo ... ti starai chiedendo "perché inserirlo nel blocco finally anziché dopo il blocco finally e completamente al di fuori di try-catch-finally".

Ad esempio, potrebbe essere perché si interrompe l'esecuzione se si genera un errore, ma si desidera comunque ripulire le risorse, come file aperti, connessioni al database, ecc.


1

Il flusso di controllo del blocco Infine è dopo il blocco Try o Catch.

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

con Eccezione 1> 2> 3> 4> 5 se 3 ha un'istruzione Return 1> 2> 3> 4

senza Eccezione 1> 2> 4> 5 se 2 ha una dichiarazione di ritorno 1> 2> 4


0

Come menzionato nella documentazione :

Un uso comune di catch e infine insieme è quello di ottenere e utilizzare risorse in un blocco try, gestire circostanze eccezionali in un blocco catch e rilasciare le risorse nel blocco finally.

Vale anche la pena leggere questo , che afferma:

Una volta trovata una clausola di cattura corrispondente, il sistema si prepara a trasferire il controllo alla prima istruzione della clausola di cattura. Prima che inizi l'esecuzione della clausola catch, il sistema esegue innanzitutto, nell'ordine, tutte le clausole infine associate alle istruzioni try più nidificate di quella che ha rilevato l'eccezione.

Quindi è chiaro che il codice che risiede in una finallyclausola verrà eseguito anche se una catchclausola precedente aveva returnun'istruzione.

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.