La différence effective entre vos exemples est négligeable tant qu'aucune exception n'est levée.
Si, cependant, une exception est levée dans la clause 'try', le premier exemple l'avalera complètement. Le deuxième exemple lèvera l'exception à l'étape suivante de la pile d'appels, de sorte que la différence dans les exemples indiqués est que l'un masque complètement toutes les exceptions (premier exemple), et l'autre (deuxième exemple) conserve les informations d'exception pour une gestion ultérieure potentielle tout en exécutant toujours le contenu de la clause «enfin».
Si, par exemple, vous deviez mettre du code dans la clause 'catch' du premier exemple qui a levé une exception (soit celle qui a été déclenchée initialement, soit une nouvelle), le code de nettoyage du lecteur ne s'exécutera jamais. S'exécute enfin indépendamment de ce qui se passe dans la clause «catch».
Ainsi, la principale différence entre «catch» et «finalement» est que le contenu du bloc «enfin» (à quelques rares exceptions près) peut être considéré comme garanti pour s'exécuter, même face à une exception inattendue, tandis que tout code suivant une clause «catch» (mais en dehors d'une clause «finalement») ne comporterait pas une telle garantie.
Soit dit en passant, Stream et StreamReader implémentent tous deux IDisposable et peuvent être encapsulés dans un bloc `` using ''. 'Utiliser' les blocs est l'équivalent sémantique de try / finally (pas de 'catch'), donc votre exemple pourrait être exprimé de manière plus laconique:
using (StreamReader reader = new StreamReader("myfile.txt"))
{
int i = 5 / 0;
}
... qui fermera et supprimera l'instance StreamReader lorsqu'elle sortira du cadre. J'espère que cela t'aides.