Super type d'exception abstraite

17

Si le lancer System.Exceptionest considéré comme si mauvais, pourquoi n'a-t-il pas été Exceptionfait abstracten premier lieu?

De cette façon, il ne serait pas possible d'appeler:

throw new Exception("Error occurred.");

Cela imposerait l'utilisation d'exceptions dérivées pour fournir plus de détails sur l'erreur qui s'est produite.

Par exemple, lorsque je veux fournir une hiérarchie d'exceptions personnalisée pour une bibliothèque, je déclare généralement une classe de base abstraite pour mes exceptions:

public abstract class CustomExceptionBase : Exception
{
    /* some stuff here */
}

Et puis une exception dérivée avec un objectif plus spécifique:

public class DerivedCustomException : CustomExceptionBase
{
    /* some more specific stuff here */
}

Ensuite, lors de l'appel d'une méthode de bibliothèque, on pourrait avoir ce bloc try / catch générique pour intercepter directement toute erreur provenant de la bibliothèque:

try
{
    /* library calls here */
}
catch (CustomExceptionBase ex)
{
    /* exception handling */
}

Est-ce une bonne pratique?

Serait-ce bien si Exceptionc'était rendu abstrait?

EDIT: Mon point ici est que même si une classe d'exception est marquée abstract, vous pouvez toujours l'attraper dans un bloc fourre-tout. Le rendre abstrait n'est qu'un moyen d'interdire aux programmeurs de lever une exception "super large". Habituellement, lorsque vous lâchez volontairement une exception, vous devez savoir de quel type il s'agit et pourquoi cela s'est produit. En imposant ainsi de lever un type d'exception plus spécifique.

marco-fiset
la source
3
+1 "La meilleure façon d'empêcher une utilisation incorrecte est de rendre cette utilisation impossible." - Scott Meyers
Steven Jeuris
3
"Serait-il bon que l'exception soit abstraite?" - Absolument pas, car tout le code .NET existant qui utilise une nouvelle exception ("...") se briserait. Cependant, "l'équipe .NET aurait-elle dû créer un résumé d'exception pour commencer?" - probablement, oui, mais il est> 10 ans trop tard maintenant :)
MattDavey

Réponses:

11

Je ne connais pas les véritables raisons pour lesquelles cela a été fait de cette façon, et dans une certaine mesure, je suis d'accord pour dire que d'empêcher des exceptions infiniment larges d'être levées serait une bonne chose.

MAIS ... lors du codage de petites applications de démonstration ou de preuves de concepts, je ne veux pas commencer à concevoir 10 sous-classes d'exceptions différentes, ni passer du temps à essayer de décider quelle est la "meilleure" classe d'exceptions pour la situation. Je préfère simplement lancer Exceptionet passer une chaîne qui explique les détails. Lorsque son code à jeter, je ne se soucient pas de ces choses et si j'obligé de se soucier de ces choses, je soit créer ma propre GenericExceptionclasse et jette que partout, ou de passer à un autre outil / langue. Pour certains projets, je conviens qu'il est important de créer correctement des sous-classes d'exceptions pertinentes, mais tous les projets ne l'exigent pas.

FrustratedWithFormsDesigner
la source
Je suis entièrement d'accord avec vous, mais la question pensait implicitement à des projets non triviaux.
marco-fiset
3

Possibilité A: c'est logiquement correct.

Vous avez raison de dire que Microsoft, ainsi que de nombreux autres, ne suggère pas de lancer new Exception()directement un pour une pléthore de raisons.

Cela étant dit, nous pouvons considérer l'idéal académique que le but d'une Exceptionhiérarchie de classe est de définir un effet de rétrécissement afin que seules les exceptions les plus spécifiques puissent être interceptées. (c'est-à ArgumentNullException- dire est plus étroit que ArgumentException).

La classe Exception ne fait pas exception (jeu de mots non prévu). Il est destiné à être l'exception la plus large possible, une "super exception" qui ne peut presque pas être interceptée car sa portée est infiniment large. «Exception» ce n'est pas abstractdans le sens où l'exception ne peut pas exister en tant qu'entité à part entière. Il peut (même s'il est vrai qu'aucun bon cas n'est encore défini - voir Possibilité B), et doit donc être publiquement constructible.

Le mot-clé «abstrait» (dans un sens purement académique) n'est applicable que lorsque la classe de base n'a aucun sens en soi - c'est-à-dire FourLeggedAnimal.

Tout cela à l'esprit, il n'y aurait aucune raison technique de faire de la classe abstract, autre que d'être une source d'aggravation pour les développeurs .

Possibilité B: Verrouillage de conception / Ils ne savaient pas

Si MS a fait cette classe abstraite, ils pourraient avoir des ennuis s'ils ont changé d'avis sur la route, car cette classe est très essentielle aux principes fondamentaux de la langue. Ils se sont déjà trompés ApplicationException, il est donc prévisible qu'ils anticipent également un changement de recommandation. (voir http://blogs.msdn.com/b/kcwalina/archive/2006/06/23/644822.aspx )

Il peut y avoir d'autres raisons (je pense que cela a peut-être à voir avec la réflexion, ou une autre raison technique), donc je fais de ce post une CW.

Kevin McCormick
la source
"Ce n'est pas parce qu'il est" super large "qu'il n'est pas abstrait." ... Mais c'est l'argument du PO n'est-ce pas. Ne devrait-il pas être abstrait dans le sens où une indication du type d'exception doit toujours être transmise.
Steven Jeuris
Bon point, je mettrai à jour ma réponse en conséquence - la nature de cette question est un peu déroutante car «abstrait» est à la fois un mot-clé de langue et le nom du concept en cours de discussion.
Kevin McCormick
@KevinMcCormick: Le terme «abstrait» est utilisé ici comme mot-clé de langue. Veuillez me dire comment je peux changer ma question afin qu'elle soit plus claire pour les futurs lecteurs?
marco-fiset
Je pense que c'est une excellente question. Toute conversion OO concernant le abstractmot clé atteint ce mur. Je ne suis pas sûr de trouver un moyen de le contourner autrement que de désigner le abstractmot - clé avec des astuces.
Kevin McCormick
2
En quoi «désabréger» une classe est-il un changement de rupture?
configurateur