9
votes

Jeter une exception C # du même type que celui attrapé?

Pourquoi (si du tout) est-ce une mauvaise idée?

  static int SalesTotal(int customerNumber)
  {
     try
     {
        throw new DivideByZeroException(); // something you didn't expect
     }
     catch (Exception ex)
     {
        throw NewException("Unable to calculate sales for customer " + customerNumber, ex);
     }
  }


5 commentaires

L'exception que vous essayez de créer peut ne pas avoir de (chaîne, exception) constructeur.


Est-ce possible ? Si cela dérive de System.Exception, comment ne pourrait-il pas?


Il est certainement possible de créer un type d'exception personnalisé qui ne fournit pas cette signature du constructeur. En général, une classe enfant n'a pas à fournir tous les mêmes constructeurs que le parent.


Bryan, merci. Votre commentaire met en évidence la chose qui fait mon exemple une "mauvaise idée" d'un point de vue technique. Votre contribution est appréciée.


Oups ... le même point que Heinzi a fait plus tôt, mais qui m'a passé. J'ai créé suffisamment d'exceptions personnalisées pour mémoriser tous les constructeurs nécessaires, mais j'ai simplement oublié pourquoi je devais leur avoir créé - ils ne sont pas hérités. Merci les gars.


7 Réponses :


1
votes

Ne l'attrapez pas du tout et laissez-la simplement bouillir - il n'y a pas de point réinventer la roue.

Votre méthode n'est pas seulement intuitive pour quelqu'un d'autre, mais vous allez également perdre la trace de la pile d'origine à partir de la première exception.


2 commentaires

Dans l'exemple original, la pile d'origine n'est pas perdue.


Pas d'accord, le contexte est roi. Si je peux dire à un utilisateur plus sur ce qu'ils faisaient au moment où une opération a échoué, un utilisateur peut souvent s'aider eux-mêmes. Retour "Impossible de convertir" Fred 'en une "erreur de conversion entier" integer "vs." integer conversion "signifie qu'un utilisateur peut s'aider eux-mêmes au lieu de simplement penser que vous avez écrit un programme stupide.



12
votes

Toutes les exceptions ont une propriété de données que vous pouvez ajouter des données supplémentaires à. Il n'est pas nécessaire de créer une nouvelle exception. Attrapez simplement l'exception existante et ajoutez vos informations, puis retirez-vous à l'exception.

De cette façon, vous avez votre gâteau et mangez-le aussi. :)

http://msdn.microsoft .Com / fr-US / bibliothèque / system.exception_members (v = vs.90) .aspx


3 commentaires

Assurez-vous simplement de repousser l'exception avec lancer; au lieu de lancer ex; ; Sinon, la trace de la pile est perdue.


... et il peut y avoir des problèmes même lorsque vous utilisez lancer; : weblogs.asp.net/fmarguerie/archive/2008/01/02/... .


Hmmm ... La collecte de données pourrait avoir certaines possibilités - mais beaucoup de possibilité d'être plutôt vague dans son utilisation.



3
votes

Je pense que vous devriez créer votre propre type d'exception personnalisé. Quel type d'information allez-vous ajouter? Comment le receveur de l'exception va-t-il savoir qu'il a des informations supplémentaires? Si vous utilisez un type personnalisé, ils auront des propriétés / méthodes supplémentaires pour afficher ou appelleront.


1 commentaires

Je suis d'accord, créez simplement un type d'exception personnalisé et ajoute éventuellement l'exception originale en tant qu'inforteException de la nouvelle.



0
votes

Cela peut avoir un sens dans certains cas. Si vous envisagez de myclass.myfunction, le public "extérieur" de l'assemblée, alors ce qui se passe à l'intérieur, il s'agit d'une boîte noire pour appeler du code. Il peut donc être plus raisonnable d'avoir cela comme le point que l'exception est arrivé aussi loin que le code d'appel va, et le type d'exception le plus raisonnable pourrait être le même type que celui capté.

Je serais prudent cependant. Dans la plupart des cas de cela se produisant, soit vous auriez dû pouvoir attraper que l'exception allait arriver, soit jetée préemptivement (si vous allez lancer, plus tôt le mieux) ou bien l'exception que vous lancez Isn ' t Vraiment le bon type (si votre code ne trouve pas de fichier, il nécessite une impression FilenotFoundException, mais si les fichiers sont un détail de mise en œuvre, ce n'est pas une exception FilenotFoundException au code d'appel), sinon l'exception originale fera. Sens parfait et il devrait simplement être autorisé à appeler ou retirer avec lancer; .

Alors, pas toujours une mauvaise idée, mais assez souvent que c'est toujours une chose suspecte à voir.


0 commentaires

5
votes

Création d'un nouveau type d'exception n'est pas une bonne option pour une méthode General comme ceci, car le code existant ne pourra pas réagir à une erreur spécifique. (Les exceptions de traduction chez API limites peuvent être utiles, cependant).

Créer une nouvelle exception du même type semble périlleux. Est-ce que la surcharge CreateInstance Copiez tous les champs de la InnerException à votre nouvelle exception extérieure? Et si un gestionnaire d'exception plus haut augmente la pile dépend de l'analyse du message ? Et si le constructeur d'exception a des effets secondaires?

IMHO, qu'est-ce que vous faites vraiment est de vous connecter, et vous seriez probablement mieux mieux en train de faire de la journalisation et d'une répétition.


3 commentaires

Quelques points valides. J'imagine que CreateInstance invoque simplement le constructeur de type, avec une chaîne et une exception (intérieure). En outre, je serais encore plus méfiant si j'ai trouvé du code figurant sur le format d'une propriété de message d'une exception.


Paysage des messages d'exception ne sont certainement pas jolie, mais je l'ai vu fait dans le code Java traitant de SQL, afin de réagir à des violations de contraintes spécifiques.


En fait ... maintenant vous en parlez, je pense que j'ai fait la même chose (dans les mêmes circonstances mais C #) moi-même.



0
votes

IMHO, il serait probablement bon d'avoir quelques types d'exception personnalisés, une hiérarchie pour des exceptions qui disent "cette opération a échoué, mais l'état du système est comme s'il n'avait jamais été tenté", une autre pour des exceptions qui disent " L'opération a échoué et l'état du système a été perturbé, mais il peut probablement être déroulé ", et une autre pour" l'opération a échoué et a échoué; l'état du système ne peut pas être approuvé. " Dans certains contextes, une classe d'exception peut être attrapée et retiré comme une autre (par exemple, si une opération censée finir de restaurer l'état du système échoue, même du point de vue de cette opération, rien n'a été perturbé, l'échec de la restauration de l'état Peut le laisser perturbé; inversement, si une opération laissait un état système perturbé mais un gestionnaire de capture a restauré l'état, il pourrait réthrow comme une "opération échouée mais l'état système n'est pas perturbé".

Je n'aime pas beaucoup l'idée d'essayer de créer des instances d'exception qui correspondent aveuglément à des types d'exception projetées, car les exceptions levées peuvent avoir des champs que les gestionnaires s'attendront à être peuplés. Je ne sais pas pourquoi Microsoft a fait des exceptions «presque» immuables. Il serait beaucoup plus agréable si des exceptions étaient obligées d'être immuables et de soutenir le clonage avec toute sémantique a transmis une immuabilité.


0 commentaires

0
votes

Seulement attraper des exceptions que vous gérez, par exemple, vous ne voulez pas que la sqléxception soit lancée à partir de votre couche de données à votre couche d'entreprise (attrapez-la, essayez OOT le gérer et jetez une datalayeException ou quelque chose comme ça).


0 commentaires