Je suis presque sûr que la réponse est OUI. Si j'utilise un bloc Try Enfin mais n'utilise pas de bloc Catch, toutes les exceptions apparaîtront. Correct?
Des réflexions sur la pratique en général?
Seth
c#
.net
vb.net
exception-handling
Seth Spearman
la source
la source
Oui. Soyez prudent . Lorsque votre bloc finally est en cours d'exécution, il est tout à fait possible qu'il soit en cours d'exécution car une exception inattendue et non gérée a été levée . Cela signifie que quelque chose est cassé et que quelque chose de complètement inattendu peut se produire.
Dans cette situation, il est probable que vous ne devriez pas du tout exécuter de code dans les blocs finally. Le code du bloc finally peut être construit pour supposer que les sous-systèmes dont il dépend sont sains, alors qu'en fait ils pourraient être profondément endommagés. Le code dans le bloc finally pourrait aggraver les choses.
Par exemple, je vois souvent ce genre de chose:
L'auteur de ce code pense: "Je suis en train de faire une mutation temporaire de l'état du monde; j'ai besoin de restaurer l'état à ce qu'il était avant d'être appelé". Mais réfléchissons à toutes les façons dont cela pourrait mal tourner.
Premièrement, l'accès à la ressource peut déjà être désactivé par l'appelant; dans ce cas, ce code le réactive, éventuellement prématurément.
Deuxièmement, si DoSomethingToTheResource lève une exception, est-ce la bonne chose à faire pour permettre l'accès à la ressource ??? Le code qui gère la ressource est rompu de manière inattendue . Ce code dit, en effet, "si le code de gestion est cassé, assurez-vous qu'un autre code peut appeler ce code cassé dès que possible, afin qu'il puisse échouer horriblement aussi ." Cela semble être une mauvaise idée.
Troisièmement, si DoSomethingToTheResource lève une exception, comment savons-nous que EnableAccessToTheResource ne lèvera pas également une exception? Quelle que soit la gravité de l'utilisation de la ressource, elle peut également affecter le code de nettoyage, auquel cas l'exception d'origine sera perdue et le problème sera plus difficile à diagnostiquer.
J'ai tendance à écrire du code comme celui-ci sans utiliser de blocs try-finally:
Maintenant, l'état n'est pas muté à moins qu'il ne soit nécessaire. Maintenant, l'état de l'appelant n'est pas perturbé. Et maintenant, si DoSomethingToTheResource échoue, nous ne réactivons pas l'accès. Nous supposons que quelque chose est profondément brisé et ne risque pas d'aggraver la situation en essayant de continuer à exécuter du code. Laissez l'appelant s'occuper du problème, s'il le peut.
Alors, quand est-ce une bonne idée d'exécuter un bloc finally? Premièrement, lorsque l'exception est attendue. Par exemple, vous pouvez vous attendre à ce qu'une tentative de verrouillage d'un fichier échoue, car quelqu'un d'autre l'a verrouillé. Dans ce cas, il est judicieux d'attraper l'exception et de la signaler à l'utilisateur. Dans ce cas, l'incertitude sur ce qui est cassé est réduite; il est peu probable que vous empireriez les choses en nettoyant.
Deuxièmement, lorsque la ressource que vous nettoyez est une ressource système rare. Par exemple, il est judicieux de fermer un descripteur de fichier dans un bloc finally. (Une "utilisation" est bien sûr juste une autre façon d'écrire un bloc try-finally.) Le contenu du fichier est peut-être corrompu, mais vous ne pouvez rien y faire maintenant. Le descripteur de fichier va finir par être fermé, donc cela pourrait aussi bien être le plus tôt possible.
la source