Pourquoi utilisons-nous enfin des blocs?

91

Pour autant que je sache, les deux extraits de code suivants auront le même objectif. Pourquoi avoir des finallyblocages?

Code A:

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

Code B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code
Mohammad Nadeem
la source
Ce n'est pas spécifique à C #, c'est une question .Net
Sruly
1
Plus besoin avec java7: AutomaticResourceManagement, essayez (new resourceDeclartion ()) {}
Kanagavelu Sugumar

Réponses:

139
  • Que se passe-t-il si une exception que vous ne gérez pas est levée? (J'espère que vous ne rattrapez pas Throwable...)
  • Que se passe-t-il si vous revenez de l'intérieur du bloc try?
  • Que se passe-t-il si le bloc catch lève une exception?

Un finallybloc s'assure que quelle que soit la façon dont vous quittez ce bloc (modulo quelques façons d'annuler explicitement tout le processus), il sera exécuté. C'est important pour le nettoyage déterministe des ressources.

Jon Skeet
la source
48
Pas nécessairement vrai; finalement ne sera pas exécuté si (1) il y a un System.exit()appel (2) il y a une boucle infinie dans l'essai ou l'un des blocs catch (3) Je tire la prise sur l'ordinateur
NullUserException
2
@Alon try {return 1; } enfin {retrun 2; } Vous obtiendrez 2
Dennis C
19
@NullUserException: D'où le bit "modulo a few way ..."
Jon Skeet
2
John Skeet vit ici sur stackoverflow, chaque question est comme une sonnette à la porte à laquelle il doit répondre :)
naikus
1
Cet article traite des (rares) conditions dans lesquelles finalement NE SERA PAS appelé.
Candamir
13

Notez que (au moins en Java, probablement aussi en C #), il est également possible d'avoir un trybloc sans a catch, mais avec un finally. Lorsqu'une exception se produit dans le trybloc, le code du finallybloc est exécuté avant que l'exception ne soit lancée plus haut:

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

Vous voudrez peut-être mettre le code que vous voulez quand même exécuter indépendamment de ce qui se passe dans votre bloc try ou catch.

De plus, si vous utilisez plusieurs catch et si vous voulez mettre du code commun à tous les blocs catch, ce serait un endroit à mettre - mais vous ne pouvez pas être sûr que tout le code de try a été exécuté.

Par exemple:

conn c1 = new connection();
try {
    c1.dosomething();
} catch (ExceptionA exa) {
    handleexA();
    //c1.close();
} catch (ExceptionB exb) {
    handleexB();
    //c1.close();
} finally {
    c1.close();
}
Balaji Natesan
la source
1
Que faire si je n'utilise pas «enfin» mais ferme la connexion?
Istiaque Ahmed
5

Enfin est toujours exécuté, alors que votre code après la capture peut ne pas l'être.

Sruly
la source
1
pourquoi pas! Si l'exception est gérée correctement, le code sera exécuté définitivement.
Mohammad Nadeem
1
@Nadeem: Voir ma réponse pour 3 raisons que cela peut ne pas arriver.
Jon Skeet
2

Même si notre application est fermée de force, il y aura certaines tâches que nous devons exécuter (comme la libération de la mémoire, la fermeture de la base de données, le verrouillage de la libération, etc.), si vous écrivez ces lignes de code dans le finallybloc, il s'exécutera, qu'une exception soit levée ou ne pas...

Votre application peut être une collection de threads, Exceptionmet fin au thread mais pas toute l'application, dans ce cas finallyest plus utile.

Dans certains cas, finallyil ne s'exécute pas, comme l'échec de la JVM, l'arrêt du thread, etc.

Sandeep P
la source
1

Parce que vous avez besoin de ce code pour s'exécuter quelles que soient les exceptions qui peuvent être levées. Par exemple, vous devrez peut-être nettoyer une ressource non gérée (la construction «using» se compile en un bloc try / finally).

Ed S.
la source
0

Il peut arriver que vous souhaitiez exécuter un morceau de code quoi qu'il arrive. Qu'une exception soit levée ou non. Puis on utilise finally.

Égalitariste
la source
0

finallyTOUJOURS s'exécute, sauf si la JVM a été arrêtée, finallyfournit simplement une méthode pour placer le code de nettoyage au même endroit.

Ce serait trop fastidieux si vous deviez mettre le code de nettoyage dans chacun des catchblocs.

Mahmoud Hanafy
la source
0

Si catch block lève une exception, le code restant ne sera pas exécuté, nous devons donc écrire le bloc en fin de compte.

Reshma Kore
la source
0

Enfin, le bloc en java peut être utilisé pour mettre du code de "nettoyage" tel que la fermeture d'un fichier, la fermeture d'une connexion, etc.


Le bloc finally ne sera pas exécuté si le programme se termine (soit en appelant System.exit (), soit en provoquant une erreur fatale qui provoque l'abandon du processus).

Aakersh Sharma
la source
0

Vous faites toujours défiler vers le bas? Voici!

Cette question m'a donné un temps difficile.

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");

qu'est-ce qui serait imprimé dans le scénario ci-dessus? Oui l'a bien deviné:

  • ex.Message - quel qu'il soit (probablement tentative de division par zéro)

  • Enfin bloquer

  • Après enfin

    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");
    

Qu'est-ce que cette impression? Rien! Il lève une erreur car le bloc catch a généré une erreur.

Dans une bonne structure de programmation, vos exceptions seraient canalisées, dans le sens où ce code sera traité à partir d'une autre couche. Pour stimuler un tel cas, je vais essayer ce code.

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

Dans ce cas, la sortie serait:

  • Enfin bloquer
  • ex.Message - quoi que ce soit.

Il est clair que lorsque vous interceptez une exception et que vous la relancez dans d'autres couches (Funneling), le code après throw n'est pas exécuté. Il agit de la même manière que le fonctionnement d'un retour à l'intérieur d'une fonction.

Vous savez maintenant pourquoi ne pas fermer vos ressources sur les codes après le bloc catch. Placez-les dans le bloc finally.

Ashique Razak
la source