J'aime utiliser: ArgumentException
, ArgumentNullException
et ArgumentOutOfRangeException
.
Il existe également d'autres options qui ne se concentrent pas tellement sur l'argument lui-même, mais jugent plutôt l'appel dans son ensemble:
InvalidOperationException
- L'argument peut être OK, mais pas dans l'état actuel de l'objet. Le crédit revient à STW (anciennement Yoooder). Votez aussi sa réponse .
NotSupportedException
- Les arguments transmis sont valides, mais ne sont simplement pas pris en charge dans cette implémentation. Imaginez un client FTP, et vous passez une commande que le client ne prend pas en charge.
L'astuce consiste à lancer l'exception qui exprime le mieux pourquoi la méthode ne peut pas être appelée telle quelle. Idéalement, l'exception devrait être détaillée sur ce qui n'a pas fonctionné, pourquoi elle est erronée et comment y remédier.
J'adore quand les messages d'erreur indiquent de l'aide, de la documentation ou d'autres ressources. Par exemple, Microsoft a fait une bonne première étape avec ses articles de la base de connaissances, par exemple "Pourquoi est-ce que je reçois un message d'erreur" Opération abandonnée "lorsque je visite une page Web dans Internet Explorer?" . Lorsque vous rencontrez l'erreur, ils vous dirigent vers l'article de la base de connaissances dans le message d'erreur. Ce qu'ils ne font pas bien, c'est qu'ils ne vous disent pas pourquoi cela a échoué.
Merci encore à STW (ex Yoooder) pour les commentaires.
En réponse à votre suivi, je lancerais un ArgumentOutOfRangeException
. Regardez ce que MSDN dit à propos de cette exception:
ArgumentOutOfRangeException
est levée lorsqu'une méthode est appelée et qu'au moins l'un des arguments passés à la méthode n'est pas une référence null ( Nothing
dans Visual Basic) et ne contient pas de valeur valide.
Donc, dans ce cas, vous transmettez une valeur, mais ce n'est pas une valeur valide, car votre plage est comprise entre 1 et 12. Cependant, la façon dont vous le documentez indique clairement ce que votre API génère. Parce que même si je pourrais dire ArgumentOutOfRangeException
, un autre développeur pourrait dire ArgumentException
. Rendez-le facile et documentez le comportement.
FormatException
: l'exception levée lorsque le format d'un argument n'est pas valide ou lorsqu'une chaîne de format composite n'est pas correctement formée.J'ai voté pour la réponse de Josh , mais j'aimerais en ajouter une de plus à la liste:
System.InvalidOperationException doit être levée si l'argument est valide, mais que l'objet est dans un état où l'argument ne doit pas être utilisé.
Mise à jour prise à partir de MSDN:
Disons que votre objet a une méthode PerformAction (action enmSomeAction), les enmSomeActions valides sont Open et Close. Si vous appelez PerformAction (enmSomeAction.Open) deux fois de suite, le deuxième appel doit lancer l'exception InvalidOperationException (puisque l'arugment était valide, mais pas pour l'état actuel du contrôle)
Puisque vous faites déjà la bonne chose en programmant de manière défensive, j'ai une autre exception à mentionner: ObjectDisposedException. Si votre objet implémente IDisposable, vous devriez toujours avoir une variable de classe qui suit l'état supprimé; si votre objet a été supprimé et qu'une méthode est appelée dessus, vous devez lever l'ObjectDisposedException:
Mise à jour: Pour répondre à votre suivi: C'est un peu une situation ambiguë, et est rendue un peu plus compliquée par un type de données générique (pas dans le sens .NET Generics) utilisé pour représenter un ensemble spécifique de données; un enum ou un autre objet fortement typé serait un ajustement plus idéal - mais nous n'avons pas toujours ce contrôle.
Je me pencherais personnellement vers l'exception ArgumentOutOfRangeException et fournirais un message indiquant que les valeurs valides sont de 1 à 12. Mon raisonnement est que lorsque vous parlez de mois, en supposant que toutes les représentations entières de mois sont valides, vous vous attendez à une valeur comprise entre 1 et 12. Si seuls certains mois (comme les mois qui avaient 31 jours) étaient valides, vous ne seriez pas confronté à un Range en soi et je lancerais une ArgumentException générique indiquant les valeurs valides, et je les documenterais également dans les commentaires de la méthode.
la source
En fonction de la valeur réelle et de l'exception qui convient le mieux:
ArgumentException
(quelque chose ne va pas avec la valeur)ArgumentNullException
(l'argument est nul alors que ce n'est pas autorisé)ArgumentOutOfRangeException
(l'argument a une valeur en dehors de la plage valide)Si ce n'est pas assez précis, dérivez simplement votre propre classe d'exceptions
ArgumentException
.La réponse de Yoooder m'a éclairé. Une entrée est invalide si elle n'est pas valide à tout moment, tandis qu'une entrée est inattendue si elle n'est pas valide pour l'état actuel du système. Donc dans le dernier cas, un
InvalidOperationException
est un choix raisonnable.la source
exception d'argument.
la source
ArgumentException :
Quelques sous-classes existent également pour des types spécifiques d'invalidité. Le lien contient des résumés des sous-types et quand ils doivent s'appliquer.
la source
Réponse courte:
ni l'un ni l'autre
Réponse plus longue:
utiliser Argument * Exception (sauf dans une bibliothèque qui est un produit sur son on, comme une bibliothèque de composants) est une odeur. Les exceptions sont de gérer des situations exceptionnelles, pas des bogues, ni des lacunes de l'utilisateur (c'est-à-dire du consommateur d'API).
Réponse la plus longue:
lancer des exceptions pour des arguments non valides est impoli, sauf si vous écrivez une bibliothèque.
Je préfère utiliser des assertions, pour deux (ou plus) raisons:
Voici à quoi ressemble la gestion des exceptions nulles (étant sarcastique, évidemment):
Des exceptions doivent être utilisées lorsque la situation est attendue mais exceptionnelle (des événements qui échappent au contrôle du consommateur, tels qu'une défaillance d'E / S). Argument * Exception est une indication d'un bogue et doit (à mon avis) être gérée par des tests et assistée avec Debug.
BTW: Dans ce cas particulier, vous auriez pu utiliser le type Month au lieu de int. C # n'est pas à la hauteur en ce qui concerne la sécurité des types (Aspect # rulez!) Mais parfois vous pouvez éviter (ou attraper au moment de la compilation) ces bogues tous ensemble.
Et oui, MicroSoft a tort à ce sujet.
la source
Il existe une ArgumentException standard que vous pouvez utiliser, ou vous pouvez sous-classer et créer la vôtre. Il existe plusieurs classes ArgumentException spécifiques:
http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx
Celui qui fonctionne le mieux.
la source