Quoi qu'il en soit, je ne sais pas quand propager une exception et quand l'envelopper, et les différences.
Pour le moment, ma compréhension me dit que l'emballage d'une exception impliquerait de prendre une exception comme DriveNotFound (dans IO) puis de l'envelopper avec l'IOException générale.
Mais avec le concept de propagation d'une exception, est-ce seulement quelque chose qui se produit si j'ai une clause catch vide? Ainsi, dans une application Web ASP.NET, il se propagerait à global.asax. Ou dans le cas d'une application Web récemment déployée, une HTTPException non gérée a donné un écran jaune de la mort et a écrit un journal sur Windows Server (il s'agit d'une application Web que je suis en train de réécrire). Ainsi, l'exception se produit dans une méthode, elle peut être gérée au niveau de la classe, affichée dans la page, puis remonter à global.asax ou Windows Server.
Pourquoi est-ce que je veux encapsuler une exception avec une exception plus générique ? La règle est de gérer une exception avec le type le plus spécifique (donc DriveNotFound pour évidemment un lecteur introuvable). De plus, comment choisir entre envelopper et remplacer une exception ?
La chaîne de gestion des exceptions est-elle simplement les clauses try et catch (ou catches) ? Je suppose d'après le libellé que oui.
Enfin, pourquoi et comment voudrais-je laisser une exception se propager dans la pile d'appels ?
J'ai lu le guide MS PandP sur la gestion des exceptions, mais je suppose que les exemples ne m'ont pas suffisamment engagé pour tout comprendre.
Cette question vient d'Enterprise Library la possibilité d'encapsuler/propager une exception, etc. C'est la propagation dont je ne suis pas sûr et les différences de remplacement/encapsulation d'une exception.
En outre, est-il acceptable d'insérer une logique complexe de gestion des erreurs dans un bloc catch (par exemple ifs/elses et des choses comme ça).
Merci
Solution du problème
Pas moins de 6 questions:-)
Mais avec le concept de propagation d'une exception, est-ce seulement quelque chose qui se produit si j'ai une clause catch vide?
Une exception se propagera vers le haut jusqu'à ce qu'elle soit interceptée par un bloc catch plus haut dans la pile d'appels qui gère soit ce type d'exception spécifique, soit un type d'exception plus proche du type de base de la hiérarchie de cette exception. Ainsi, par exemple, toutes les exceptions gérées dérivent de System.Exception, donc un bloc catch qui intercepte System.Exception interceptera toutes les exceptions gérées.
Pourquoi est-ce que je veux encapsuler une exception avec une exception plus générique ?
Je ne sais pas ce que vous entendez par "envelopper". Voulez-vous dire attraper une exception, la remplacer par une autre et ajouter l'original en tant que propriété InnerException de la nouvelle exception ? Ou autre chose?
Je pense qu'il y a rarement une bonne raison de remplacer une exception par une exception plus générique. Mais vous pouvez certainement remplacer une exception par une autre exception, pour une ou plusieurs des 3 raisons:
- Pour masquer les détails d'implémentation à l'appelant.
- Pour améliorer le niveau d'une abstraction afin qu'elle soit plus significative pour l'appelant.
- Pour lancer une exception personnalisée très spécifique au problème en cours.
De plus, comment choisir entre envelopper et remplacer une exception ?
Je suis désolé, mais je ne comprends toujours pas comment vous définissez ces deux comme différents.
La chaîne de gestion des exceptions est-elle simplement les clauses try et catch (ou catches) ?
Voici les bases de ce qui se passe lorsqu'une exception est levée :
Le CLR parcourt séquentiellement la liste des blocs Catch dans le bloc Try...End Try local, à la recherche d'un bloc Catch local avec un filtre d'exception correspondant à l'exception levée.
Si un bloc Catch local a un filtre d'exception qui correspond à l'exception exacte qui a été levée, le code de ce bloc Catch est exécuté, suivi du code du bloc Enfin. Ensuite, l'exécution continue à la première instruction suivant End Try.
Alternativement, si l'exception qui a été levée dérive de l'exception spécifiée par un bloc Catch local, les mêmes actions se produisent comme décrit dans la deuxième étape. Par exemple, un filtre d'exception qui intercepte ArgumentException interceptera également les exceptions dérivées de ArgumentException, telles que ArgumentNullException, InvalidEnumArgumentException, DuplicateWaitObjectException et ArgumentOutOfRangeException.
Si aucun bloc Catch local ne correspond à l'exception levée, le CLR remonte la pile des appels, méthode par méthode, à la recherche d'un bloc Catch qui souhaite répondre à l'exception. Si aucun bloc Catch correspondant n'est trouvé dans la pile des appels, l'exception est considérée comme non gérée.
Alternativement, si un bloc Catch correspondant est trouvé quelque part dans la pile des appels, le code de chaque bloc finally entre le throw et le catch est exécuté. Cela commence par le final appartenant au bloc Try où l'exception a été levée et se termine par le final dans la méthode sous la méthode où l'exception a été interceptée.
Une fois ce nettoyage terminé pour toutes les méthodes ci-dessous où l'exception a été interceptée, le contrôle est transféré au bloc Catch qui a intercepté l'exception, et ce code est exécuté. Le prochain à exécuter est le bloc Enfin de l'essai où l'exception a été interceptée. Maintenant que la pile des appels a été déroulée et que le nettoyage des erreurs est terminé, la dernière étape consiste à poursuivre l'exécution à la première instruction suivant End Try où l'exception a été interceptée.
Si le code d'un bloc Catch provoque la levée d'une autre exception, l'exception d'origine est automatiquement ajoutée à la nouvelle exception à l'aide de la propriété InnerException. De cette manière, les exceptions peuvent être empilées sans aucune perte d'informations.
Vous devez éviter de placer du code de nettoyage dans un bloc finally susceptible de lever une exception, à moins que ce code ne se trouve dans son propre bloc Try. Sans cette protection supplémentaire, le CLR se comporte comme si la nouvelle exception était levée après la fin après le bloc finally et recherche dans la pile des appels un bloc Catch distant qui souhaite répondre à la nouvelle exception. L'exception d'origine sera perdue à moins que le bloc Catch d'origine ne l'ait enregistrée.
Enfin, pourquoi et comment voudrais-je laisser une exception se propager dans la pile d'appels ?
Pourquoi : Chaque fois que vous ne comprenez pas spécifiquement l'exception et que vous ne savez pas comment vous en remettre, vous devez la laisser se propager vers le haut.
Comment : en n'interceptant que les types d'exceptions que vous comprenez et savez gérer. Parfois, vous avez besoin des détails d'une exception pour effectuer une récupération appropriée. Dans ce cas, vous pouvez l'attraper, faire la récupération, puis le relancer en utilisant le lancer; déclaration.
En outre, est-il acceptable d'insérer une logique complexe de gestion des erreurs dans un bloc catch (par exemple ifs/elses et des choses comme ça).
En règle générale, oui, car toute nouvelle exception causée par le code de votre bloc Catch sera automatiquement associée à l'ancienne exception via la propriété InnerException. Mais il n'est pas sage de provoquer ce mécanisme si vous pouvez l'éviter, donc plus le code est simple, mieux c'est. Une autre bonne raison de garder votre code Catch simple est qu'il ne subira souvent pas le même degré de test que votre code principal.
Aucun commentaire:
Enregistrer un commentaire