Domanda

Sintassi a parte, qual è la differenza tra

try {
}
catch() {
}
finally {
    x = 3;
}

E

try {
}
catch() {
}

x = 3;

modificare:in .NET 2.0?


COSÌ

try {
    throw something maybe
    x = 3
}
catch (...) {
    x = 3
}

è comportamentalmente equivalente?

È stato utile?

Soluzione

Dipende dalla lingua in quanto potrebbero esserci alcune lievi differenze semantiche, ma l'idea è che verrà eseguito (quasi) sempre, anche se il codice nel blocco try genera un'eccezione.

Nel secondo esempio, se il codice nel blocco catch ritorna o termina, x = 3 non verrà eseguito.Nella prima lo farà.

Nella piattaforma .NET, in alcuni casi non avverrà l'esecuzione del blocco final:Eccezioni di sicurezza, sospensioni di thread, spegnimento del computer :), ecc.

Altri suggerimenti

Bene, per prima cosa, se RETURN all'interno del blocco try, last verrà comunque eseguito, ma il codice elencato sotto il blocco try-catch-finally no.

In Giava:

Alla fine viene sempre chiamato, indipendentemente dal fatto che l'eccezione sia stata catturata correttamente in catch(), o in effetti se si abbia qualche cattura.

prova a prendere Finalmente è un costrutto piuttosto importante.Puoi essere sicuro che anche se viene lanciata un'eccezione, il codice in last block verrà eseguito.È molto importante nella gestione delle risorse esterne liberarle.La raccolta dei rifiuti non farà al caso tuo.In fondo non avresti dovuto farlo ritorno dichiarazioni o generare eccezioni.È possibile farlo, ma è una cattiva pratica e può portare a risultati imprevedibili.

Se provi questo esempio:

try {
  return 0;
} finally {
  return 2;
}

Il risultato sarà 2 :)

Confronto con altre lingue: Ritorno da finalmente

Ci sono diverse cose che rendono utile un blocco final:

  1. Se si ritorna dai blocchi try o catch, il blocco last viene comunque eseguito, subito prima che il controllo venga restituito alla funzione chiamante
  2. Se si verifica un'eccezione all'interno del blocco catch o si verifica un tipo di eccezione non rilevata nel blocco try, il codice nel blocco last viene comunque eseguito.

Questi rendono infine i blocchi eccellenti per chiudere handle o socket di file.

Nel caso in cui try e catch siano vuoti, non c'è differenza.Altrimenti puoi essere sicuro che alla fine verrà eseguito.

Se, ad esempio, lanci una nuova eccezione nel tuo catchblock (rethrow), l'assegnazione verrà eseguita solo se si trova nel last-block.

Normalmente un final viene utilizzato per ripulire te stesso (chiudere connessioni DB, file handle e simili).

Non dovresti mai usare istruzioni di controllo (return, break, continue) in unfine, poiché questo può essere un incubo di manutenzione ed è quindi considerato una cattiva pratica

Il blocco infine verrà sempre chiamato (beh, non proprio Sempre ...) anche se viene generata un'eccezione o viene raggiunta un'istruzione return (sebbene ciò possa dipendere dalla lingua).È un modo per fare pulizia che sai che verrà sempre chiamato.

@iAn e @mats:

Di regola, non "demolirei" nulla in Finalmente {} che sia stato "impostato" all'interno del tentativo {}.Sarebbe meglio estrarre la creazione dello stream al di fuori del try {}.Se è necessario gestire un'eccezione durante la creazione dello stream, è possibile farlo in un ambito più ampio.

StreamReader stream = new StreamReader("foo.bar");  
try {
    mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally {
    stream.close();  
}

In questo modo puoi ripulire eventuali connessioni aperte, ecc.inizializzato nel blocco try.Se aprissi una connessione e poi si verificasse un'eccezione, quell'eccezione non verrebbe chiusa correttamente.Questo tipo di scenario è lo scopo del blocco finale.

Si suppone che il blocco final venga eseguito indipendentemente dal fatto che tu abbia rilevato l'eccezione o meno.Vedere Prova / Cattura / Finalmente esempio

@Ed, potresti pensare a qualcosa come a catch(...) che rileva un'eccezione non specificata in C++.

Ma finally è il codice che verrà eseguito indipendentemente da ciò che accade nel file catch blocchi.

Microsoft ha una pagina di aiuto su prova finalmente per C#

Il blocco last ha lo stesso ambito di try/catch, quindi avrai accesso a tutte le variabili definite al suo interno.

Immagina di avere un gestore di file, questa è la differenza nel modo in cui verrebbe scritto.

try
{
   StreamReader stream = new StreamReader("foo.bar");
   stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
   stream.close();
}

rispetto a

StreamReader stream = null;
try
{
    stream = new StreamReader("foo.bar");
    stream.write("foo");
} catch(Exception e) {} // ignore

if (stream != null)
    stream.close();

Ricorda però che qualsiasi cosa all'interno alla fine non è garantita per funzionare.Immagina di ricevere un segnale di interruzione, che Windows si blocchi o che la corrente venga a mancare.Affidarsi a finalmente per il codice critico per l'azienda è negativo.

Qualsiasi codice in Finalmente viene eseguito anche in caso di eccezione non gestita.In genere il codice final viene utilizzato per ripulire le dichiarazioni locali di codice non gestito utilizzando .dispose().

Infine i blocchi ti consentono, come sviluppatore, di riordinare te stesso, indipendentemente dalle azioni del codice precedente nel blocco try{} riscontrato errori, e se altri lo hanno sottolineato, rientra principalmente nell'ambito della liberazione di risorse - chiusura puntatori/socket/set di risultati, restituzione di connessioni a un pool ecc.

@mats ha assolutamente ragione nel dire che esiste sempre il rischio di errori "gravi": infine i blocchi non dovrebbero includere codice mission-critical, che dovrebbe sempre essere eseguito a livello transazionale all'interno del try{}

@mats ancora - La vera bellezza è che ti consente di eliminare le eccezioni dai tuoi metodi e di garantire comunque il riordino:

try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
    //Swallow this    
    logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
    //More serious, throw this one back
    throw(e);
}
finally
{
stream.close();
}

Quindi, possiamo catturare molti tipi di eccezione, elaborarli in modo diverso (il primo consente l'esecuzione di qualsiasi cosa oltre try{}, il secondo restituisce effettivamente), ma chiarire sempre in modo pulito e ordinato.

In Java, lo usi per tutto ciò che vuoi eseguire indipendentemente dal fatto che tu abbia utilizzato un "return", abbia semplicemente eseguito il blocco try o che sia stata rilevata un'eccezione.

Ad esempio, chiudendo una sessione di database o una connessione JMS o deallocando alcune risorse del sistema operativo.

Immagino che sia simile in .NET?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top