Question

Syntaxe mise à part, quelle est la différence entre

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

et

try {
}
catch() {
}

x = 3;

modifier:dans .NET 2.0 ?


donc

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

est-ce que le comportement est équivalent ?

Était-ce utile?

La solution

Cela dépend de la langue car il peut y avoir de légères différences sémantiques, mais l'idée est qu'il s'exécutera (presque) toujours, même si le code du bloc try a levé une exception.

Dans le deuxième exemple, si le code du bloc catch retourne ou s'arrête, le x = 3 ne sera pas exécuté.Dans le premier cas, ce sera le cas.

Dans la plateforme .NET, dans certains cas, l'exécution du bloc final n'aura pas lieu :Exceptions de sécurité, suspensions de threads, arrêt de l'ordinateur :), etc.

Autres conseils

Eh bien, d'une part, si vous RETOURNEZ à l'intérieur de votre bloc try, le final sera toujours exécuté, mais le code répertorié sous le bloc try-catch-finally ne le sera pas.

En Java :

Enfin, il est toujours appelé, que l'exception ait été correctement interceptée dans catch() ou même si vous avez un catch.

essayez d'attraper enfin est une construction assez importante.Vous pouvez être sûr que même si une exception est levée, le code du bloc final sera exécuté.Il est très important lors de la gestion des ressources externes de les libérer.La collecte des déchets ne fera pas cela pour vous.En fin de compte, tu n'aurais pas dû retour déclarations ou lever des exceptions.C’est possible, mais c’est une mauvaise pratique et peut conduire à des résultats imprévisibles.

Si vous essayez cet exemple :

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

Le résultat sera 2 :)

Comparaison avec d'autres langues : Retour de enfin

Il y a plusieurs choses qui rendent un bloc final utile :

  1. Si vous revenez des blocs try ou catch, le bloc enfin est toujours exécuté, juste avant que le contrôle ne soit rendu à la fonction appelante.
  2. Si une exception se produit dans le bloc catch ou si un type d'exception non intercepté se produit dans le bloc try, le code du bloc enfin est toujours exécuté.

Ceux-ci rendent les blocs final excellents pour fermer les descripteurs de fichiers ou les sockets.

Dans le cas où le try et le catch sont vides, il n'y a aucune différence.Sinon, vous pouvez être sûr que le final sera exécuté.

Si, par exemple, vous lancez une nouvelle exception dans votre catchblock (rethrow), l'affectation ne sera exécutée que si elle se trouve dans le bloc final.

Normalement, un final est utilisé pour nettoyer après vous (fermer les connexions DB, les descripteurs de fichiers, etc.).

Vous ne devez jamais utiliser d'instructions de contrôle (return, break, continue) dans un final, car cela peut être un cauchemar de maintenance et est donc considéré comme une mauvaise pratique.

Le bloc final sera toujours appelé (enfin pas vraiment toujours ...) même si une exception est levée ou si une instruction return est atteinte (bien que cela puisse dépendre de la langue).C'est une façon de nettoyer qui, vous le savez, sera toujours appelée.

@iAn et @mats :

En règle générale, je ne "démonterais" rien dans final {} qui était "mis en place" dans le cadre du try {}.Il serait préférable d'extraire la création du flux en dehors du try {}.Si vous devez gérer une exception lors de la création du flux, cela pourrait être fait dans une plus grande portée.

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

Vous pouvez ainsi nettoyer toutes les connexions ouvertes, etc.initialisé dans le bloc try.Si vous ouvrez une connexion et qu'une exception se produit, cette exception ne sera pas correctement fermée.C'est à ce type de scénario que sert le bloc final.

Le bloc final est censé s'exécuter, que vous ayez détecté l'exception ou non.Voir Exemple Try / Catch / Enfin

@Ed, vous pensez peut-être à quelque chose comme un catch(...) qui intercepte une exception non spécifiée en C++.

Mais finally est du code qui sera exécuté quoi qu'il arrive dans le catch blocs.

Microsoft a une page d'aide sur essayez enfin pour C#

Le bloc final a la même portée que le try/catch, vous aurez donc accès à toutes les variables définies à l'intérieur.

Imaginez que vous ayez un gestionnaire de fichiers, c'est la différence dans la façon dont il serait écrit.

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

par rapport à

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

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

N'oubliez pas cependant que tout ce qui se trouve à l'intérieur n'est finalement pas garanti de fonctionner.Imaginez que vous recevez un signal d'abandon, que Windows plante ou que l'alimentation soit coupée.S'appuyer enfin sur du code critique pour l'entreprise est une mauvaise chose.

Tout code dans le final est exécuté même en cas d'exception non gérée.Généralement, le code final est utilisé pour nettoyer les déclarations locales de code non géré à l'aide de .dispose().

Enfin, les blocs vous permettent, en tant que développeur, de faire le ménage après vous-même, quelles que soient les actions du code précédent dans le bloc try{} qui ont rencontré des erreurs, et si d'autres l'ont souligné, cela relève principalement de la libération de ressources - fermeture pointeurs/sockets/ensembles de résultats, renvoyant des connexions à un pool, etc.

@mats a tout à fait raison de dire qu'il y a toujours un risque d'échecs "durs" - enfin, les blocs ne devraient pas inclure de code critique pour la mission, qui doit toujours être effectué de manière transactionnelle dans le try{}

@mats encore - La vraie beauté est que cela vous permet de supprimer des exceptions de vos propres méthodes, tout en garantissant que vous faites le ménage :

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

Ainsi, nous pouvons détecter de nombreux types d'exceptions, les traiter différemment (la première permet l'exécution de tout ce qui va au-delà de try{}, la seconde renvoie effectivement), mais toujours clarifier proprement et proprement.

En Java, vous l'utilisez pour tout ce que vous souhaitez exécuter, que vous ayez utilisé un "retour", que vous ayez simplement exécuté le bloc try ou qu'une exception ait été interceptée.

Par exemple, fermer une session de base de données ou une connexion JMS, ou désallouer une ressource du système d'exploitation.

Je suppose que c'est similaire dans .NET ?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top