117 votes

Meilleure exception pour un argument de type générique invalide

Je suis actuellement en train d'écrire du code pour UnconstrainedMelody qui possède des méthodes génériques pour les enums.

Maintenant, j'ai une classe statique avec un tas de méthodes qui sont seulement destiné à être utilisé avec les enums "flags". Je ne peux pas ajouter cela comme une contrainte... donc il est possible qu'ils soient appelés avec d'autres types d'enum. Dans ce cas, j'aimerais lancer une exception, mais je ne sais pas laquelle lancer.

Juste pour que ce soit concret, si j'ai quelque chose comme ça :

// Returns a value with all bits set by any values
public static T GetBitMask<T>() where T : struct, IEnumConstraint
{
    if (!IsFlags<T>()) // This method doesn't throw
    {
        throw new ???
    }
    // Normal work here
}

Quelle est la meilleure exception à lancer ? ArgumentException semble logique, mais c'est un type plutôt qu'un argument normal, ce qui pourrait facilement embrouiller les choses. Devrais-je introduire mon propre TypeArgumentException classe ? Utilisez InvalidOperationException ? NotSupportedException ? Autre chose ?

Je plutôt ne pas créer ma propre exception pour cela, sauf si c'est clairement la bonne chose à faire.

53voto

Jeff Sternal Points 30147

NotSupportedException sonne comme s'il était tout à fait adapté, mais la documentation indique clairement qu'il doit être utilisé dans un but différent. D'après les remarques de la classe MSDN :

Il existe des méthodes qui ne sont pas supportées dans la classe de base, avec s'attendre à ce que ces méthodes soient implémentées dans les classes dérivées à la place. La classe dérivée peut n'implémenter qu'un sous-ensemble des méthodes de la classe de base, et lancer NotSupportedException pour les méthodes non prises en charge.

Bien sûr, il y a une façon de faire NotSupportedException est manifestement suffisant, surtout compte tenu de sa signification de bon sens. Cela dit, je ne suis pas sûr que ce soit juste.

Compte tenu de l'objectif de Mélodie sans contrainte ...

Il y a plusieurs choses utiles qui peuvent être faites avec les méthodes/classes génériques. où il y a une contrainte de type de "T : enum" ou "T : délégué" - mais malheureusement, ces contraintes sont interdites en C#.

Cette bibliothèque utilitaire contourne les interdictions d'utiliser ildasm/ilasm ...

... il semble qu'un nouveau Exception pourrait s'imposer malgré la lourde charge de la preuve à laquelle nous devons nous plier avant de créer des services personnalisés. Exceptions . Quelque chose comme InvalidTypeParameterException pourrait être utile dans l'ensemble de la bibliothèque (ou peut-être pas - il s'agit sûrement d'un cas limite, non ?).

Les clients devront-ils être en mesure de faire la distinction avec les exceptions de la BCL ? Quand un client pourrait-il accidentellement appeler cette fonction en utilisant une fonction vanille enum ? Comment répondriez-vous aux questions posées par la réponse acceptée à la question suivante Quels facteurs doivent être pris en compte lors de l'écriture d'une classe d'exception personnalisée ?

28voto

JaredPar Points 333733

J'éviterais NotSupportedException. Cette exception est utilisée dans le cadre où une méthode n'est pas implémentée et où il existe une propriété indiquant que ce type d'opération n'est pas pris en charge. Elle n'a pas sa place ici

Je pense que InvalidOperationException est l'exception la plus appropriée que vous pourriez lancer ici.

13voto

Remus Rusanu Points 159382

La programmation générique ne devrait pas provoquer de rejet à l'exécution pour des paramètres de type invalide. Elle ne devrait pas être compilée, il faudrait une application au moment de la compilation. Je ne sais pas ce que IsFlag<T>() mais peut-être pouvez-vous transformer cela en une application au moment de la compilation, comme essayer de créer un type qui ne peut être créé qu'avec des "drapeaux". Peut-être qu'un traits peut vous aider.

Mise à jour

Si vous doit lancer, je voterais pour InvalidOperationException. Le raisonnement est le suivant : les types génériques ont paramètres et les erreurs liées aux paramètres (de méthode) sont centrées sur la hiérarchie ArgumentException. Cependant, les recommandation sur ArgumentException indique que

si la défaillance n'implique pas le arguments eux-mêmes, alors InvalidOperationException doit être utilisée.

Il y a au moins un acte de foi là-dedans, que méthode les paramètres de les recommandations doivent également s'appliquer à Générique mais il n'y a rien de mieux dans la hiérarchie des SystemException, à mon avis.

10voto

Robban Points 2984

J'utiliserais NotSupportedException puisque c'est ce que vous dites. D'autres enums que ceux qui sont spécifiques sont non supporté . Cela serait bien sûr indiqué plus clairement dans le message d'exception.

8voto

Mehrdad Afshari Points 204872

Je choisirais NotSupportedException . Alors que ArgumentException a l'air bien, c'est vraiment attendu quand un argument passé à une méthode est inacceptable. Un argument de type est une caractéristique de définition pour la méthode réelle que vous voulez appeler, pas un véritable "argument". InvalidOperationException doit être lancée lorsque l'opération que vous effectuez peut être valide dans certains cas, mais qu'elle est inacceptable dans cette situation particulière.

NotSupportedException est déclenché lorsqu'une opération n'est pas prise en charge de manière inhérente. Par exemple, lors de l'implémentation d'une interface où un membre particulier n'a pas de sens pour une classe. Cela ressemble à une situation similaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X