Est-ce une mauvaise pratique de revenir depuis un bloc try catch enfin?

128

Je suis donc tombé sur un code ce matin qui ressemblait à ceci:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Maintenant, ce code se compile correctement et fonctionne comme il se doit, mais il ne semble pas juste de revenir à partir d'un bloc try, surtout s'il y a finalement un associé.

Mon principal problème est que se passe-t-il si le lance finalement une exception de sa part? Vous avez une variable retournée mais aussi une exception à traiter ... donc je suis intéressé de savoir ce que les autres pensent du retour d'un bloc try?

lomaxx
la source
13
L'un des avantages de ce style est que vous n'avez pas à déclarer en xdehors du trybloc. Vous pouvez garder sa déclaration près de son utilisation.
David R Tribble

Réponses:

169

Non, ce n'est pas une mauvaise pratique. Mettre returnlà où cela a du sens améliore la lisibilité et la maintenabilité et rend votre code plus simple à comprendre. Vous ne devriez pas vous en soucier car le finallybloc sera exécuté si une returninstruction est rencontrée.

Mehrdad Afshari
la source
19

Le Final sera exécuté quoi qu'il arrive, donc peu importe.

Ed S.
la source
9
Non, en fait, il ne s'agit pas seulement de se brancher, il existe des exceptions appelées exceptions asynchrones telles que StackOverflowException, ThreadAbortException et OutOfMemoryException qui peuvent empêcher l'exécution du bloc finally. Découvrez les régions d'exécution contraintes pour gérer ces scénarios.
Mehrdad Afshari
Ces lien l'expliquent: return Statement and try ... catch ... finally Statement
amit jha
14

Personnellement, j'éviterais ce genre de codage car je n'ai pas envie de voir les déclarations return avant les déclarations finally.

Mon esprit est simple et il traite les choses de manière plutôt linéaire. Par conséquent, lorsque je parcourrai le code de la marche à sec, j'aurai tendance à penser qu'une fois que je pourrai atteindre l'instruction de retour, tout ce qui suit n'a pas d'importance, ce qui est évidemment assez faux dans ce cas (non pas que cela affecterait l'instruction de retour, mais quels pourraient être les effets secondaires).

Ainsi, j'arrangerais le code de sorte que l'instruction return apparaisse toujours après les instructions finally.

Conrad
la source
9

Cela peut répondre à votre question

Que se passe-t-il vraiment lors d'un essai {return x; } enfin {x = null; } déclaration?

En lisant cette question, il semble que vous puissiez avoir une autre structure try catch dans l'instruction finally si vous pensez qu'elle pourrait lever une exception. Le compilateur déterminera quand renvoyer la valeur.

Cela dit, il serait peut-être préférable de restructurer votre code de toute façon pour ne pas vous embrouiller plus tard ou quelqu'un d'autre qui pourrait ne pas être au courant de cela également.

Spencer Ruport
la source
hmmm très intéressant. Cela signifie donc que c'est sûr, mais cela signifie-t-il que cela devrait être évité?
lomaxx
3
Personnellement, je pense que cela rend la lisibilité de votre code un peu difficile et que cela seul suffirait à me faire trouver une autre façon de structurer le code. Mais en réalité, c'est juste une préférence personnelle.
Spencer Ruport
3
J'ai tendance à être d'accord avec votre préférence personnelle :)
lomaxx
Je pense que le retour est bien là où il est. La méthode retournera la valeur, sauf si une exception est levée; peu importe si l'exception survient dans le code de nettoyage final.
Lawrence Dol
Notez que la restriction sur le retour de finally n'est pas présente en Java (mais je pense que la restriction est bonne - bravo à C #).
Lawrence Dol
5

Fonctionnellement, il n'y a pas de différence.

Cependant, il y a une raison pour ne pas le faire. Les méthodes plus longues avec plusieurs points de sortie sont souvent plus difficiles à lire et à analyser. Mais cette objection a plus à voir avec les instructions return qu'avec les blocs catch et finally.

Ifeanyi Echeruo
la source
Je contesterais cela car vous pourriez vous retrouver avec plus d'imbrication qui rend également plus difficile la lecture d'une complexité cyclomatique plus élevée
matt_lethargic
3

Dans votre exemple, l'une ou l'autre manière est équivalente, je ne serais même pas surpris si le compilateur générait le même code. Si une exception se produit dans le bloc finally, vous rencontrez les mêmes problèmes que vous placiez l'instruction return dans le bloc ou en dehors de celui-ci.

La vraie question est stylistiquement ce qui est le mieux. J'aime écrire mes méthodes pour qu'il n'y ait qu'une seule instruction return, de cette façon, il est plus facile de voir le flux de la méthode, il s'ensuit que j'aime aussi mettre l'instruction return en dernier, donc il est facile de voir que c'est la fin de la méthode et ce qu'elle renvoie.

Je pense qu'avec la déclaration de retour si bien placée comme dernière déclaration, d'autres sont moins susceptibles de venir et de saupoudrer plusieurs déclarations de retour dans d'autres parties de la méthode.

Être averti
la source