Quel type d’exception utiliser lorsqu’une propriété ne peut pas être nulle?

Dans mon application, je dois lancer une exception si une propriété d’une classe spécifique est nulle ou vide (si c’est une chaîne). Je ne sais pas quelle est la meilleure exception à utiliser dans ce cas. Je détesterais créer une nouvelle exception et je ne suis pas sûr si ArgumentNullException est approprié dans ce cas.

Dois-je créer une nouvelle exception ou une exception que je peux utiliser?

Cela ne me dérange pas de lancer une exception ApplicationException.

Les directives MSDN pour les exceptions standard stipulent:

Utilisez la valeur pour le nom du paramètre de valeur implicite des parameters de propriété.

L’exemple de code suivant montre une propriété qui émet une exception si l’appelant passe un argument null.

public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } } 

En outre, les directives MSDN pour la conception de propriété indiquent:

Évitez de jeter des exceptions aux getters de propriété.

Les acquéreurs de biens doivent être des opérations simples sans aucune condition préalable. Si un getter peut lancer une exception, envisagez de modifier la propriété pour en faire une méthode. Cette recommandation ne s’applique pas aux indexeurs. Les indexeurs peuvent lancer des exceptions en raison d’arguments non valides.

Il est valide et acceptable de lancer des exceptions à partir d’un setter de propriétés.

Lancez donc ArgumentNullException dans le setter sur null et ArgumentException sur la chaîne vide, et ne faites rien dans getter. Étant donné que le setter lance et que vous avez uniquement access au champ de sauvegarde, il est facile de vous assurer qu’il ne contiendra pas une valeur non valide. Avoir le lancer est alors inutile. Cela pourrait cependant être un bon endroit pour utiliser Debug.Assert .

Si vous ne pouvez vraiment pas fournir une valeur par défaut appropriée, alors je suppose que vous avez trois options:

  1. Il suffit de retourner ce qui se trouve dans la propriété et de documenter ce comportement dans le cadre du contrat d’utilisation. Laissez l’appelant y faire face. Vous pouvez également demander une valeur valide dans le constructeur. Cela peut cependant être totalement inapproprié pour votre application.

  2. Remplacez la propriété par des méthodes: une méthode setter qui émet une valeur non valide et une méthode getter qui InvalidOperationException lorsque la valeur atsortingbuée à la propriété n’a jamais été valide.

  3. Lancez InvalidOperationException partir de getter, car vous pourriez considérer que la propriété n’a jamais été affectée à un état invalide. Bien que vous ne devriez pas normalement lancer de getters, je suppose que cela pourrait être une bonne raison de faire une exception.

Si vous choisissez les options 2 ou 3, vous devez également inclure une méthode TryGet qui renvoie un bool qui indique si la propriété a été définie sur une valeur valide et, si oui, renvoie cette valeur dans un paramètre out . Sinon, vous forcez les appelants à se préparer à gérer une InvalidOperationException , à moins qu’ils aient préalablement défini la propriété eux-mêmes et qu’ils sachent ainsi qu’elle ne lançera pas. Comparez int.Parse et int.TryParse .

Je suggère d’utiliser l’option 2 avec la méthode TryGet. Il ne viole aucune directive et impose des exigences minimales au code d’appel.


A propos des autres suggestions
ApplicationException est bien trop général. ArgumentException est un peu trop général pour null , mais très bien sinon. MSDN docs à nouveau :

Lancez l’exception la plus spécifique (la plus dérivée) appropriée. Par exemple, si une méthode reçoit un argument null (Nothing en Visual Basic), elle doit lancer System.ArgumentNullException à la place de son type de base System.ArgumentException.

En fait, vous ne devriez pas utiliser ApplicationException ( docs ):

Dérivez les exceptions personnalisées de la classe T: System.Exception plutôt que de la classe T: System.ApplicationException.

On pensait à l’origine que les exceptions personnalisées devaient dériver de la classe ApplicationException; Cependant, cela n’a pas été trouvé pour append une valeur significative. Pour plus d’informations, voir Meilleures pratiques pour gérer les exceptions.

InvalidOperationException n’est pas destiné aux cas où les arguments d’une méthode ou d’une propriété ne sont pas valides, mais lorsque l’ opération dans son ensemble n’est pas valide ( docs ). Il ne faut pas le lancer depuis le setter:

Lancez une exception System.InvalidOperationException si elle est dans un état inapproprié. System.InvalidOperationException doit être levé si un ensemble de propriétés ou un appel de méthode n’est pas approprié compte tenu de l’état actuel de l’object. Par exemple, l’écriture dans un System.IO.FileStream qui a été ouvert pour la lecture doit générer une exception System.InvalidOperationException.

Incidemment, InvalidOperationException est InvalidOperationException lorsque l’opération n’est pas valide pour l’état actuel de l’object. Si l’opération est toujours invalide pour la classe entière, vous devez utiliser NotSupportedException .

Je lancerais une InvalidOperationException . MSDN le dit “est renvoyé lorsqu’un appel de méthode n’est pas valide pour l’état actuel de l’object.”

Eh bien, ce n’est pas un argument, si vous faites référence à une propriété d’une classe. Vous ne devez donc pas utiliser ArgumentException ou ArgumentNullException.

NullReferenceException se produirait si vous laissiez les choses seules, donc je suppose que ce n’est pas ce que vous cherchez.

Donc, utiliser ApplicationExeption ou InvalidOperationException serait probablement votre meilleur choix, en veillant à donner une chaîne de caractères significative pour décrire l’erreur.

Il est tout à fait approprié de lancer ArgumentNullException si quelqu’un essaie d’ atsortingbuer la valeur null.

Une propriété ne doit jamais lancer une opération de lecture.

Le constructeur a-t-il défini une valeur non nulle? Si oui, je voudrais juste lancer ArgumentNullException du setter.

Si le problème est qu’un membre d’un argument, et non l’argument lui-même, est nul, je pense que le meilleur choix est l’ ArgumentException plus générique. ArgumentNullException ne fonctionne pas ici car l’argument n’est en fait pas nul. Au lieu de cela, vous avez besoin du type d’exception “quelque chose ne va pas avec votre argument”.

Un message détaillé pour le constructeur serait très approprié ici

S’il ne peut pas être nul ou vide, demandez à votre installateur de ne pas autoriser les valeurs NULL ou vides, ou lancez une exception ArgumentException si tel est le cas.

De plus, exigez que la propriété soit définie dans le constructeur.

De cette façon, vous forcez une valeur valide, plutôt que de revenir plus tard et en disant que vous ne pouvez pas déterminer le solde du compte lorsque le compte n’est pas défini.

Mais je serais d’accord avec la réponse de bduke.

Il existe un précédent pour étendre l’interprétation de ArgumentNullException à ce qui signifie que “l’argument de chaîne est null ou vide”: System.Windows.Clipboard.SetText lancera une ArgumentNullException dans ce cas.

Donc je ne verrais rien de mal à utiliser ceci plutôt que l’argumentException plus général dans votre setter de propriétés, à condition que vous le documentiez.

Il suffit de lancer n’importe quoi tant que le message d’erreur est utile pour un développeur. Cette classe d’exception ne devrait jamais se produire en dehors du développement, de toute façon.