Quelle exception lancer à partir d’un setter de propriétés?

J’ai une propriété de chaîne qui a une longueur maximale car les données sont liées à une firebase database. Quelle exception dois-je lancer si l’appelant tente de définir une chaîne dépassant cette longueur?

Par exemple, ce code C #:

public ssortingng MyProperty { get { return _MyBackingField; } set { if (value.Length > 100) throw new FooException("MyProperty has a maximum length of 100."); _MyBackingField = value; } } 

J’ai considéré ArgumentException , mais ça ne semble pas correct. Techniquement , il s’agit d’une fonction – MyProperty_set(ssortingng value) – il est donc possible de faire une MyProperty_set(ssortingng value) à ArgumentException , mais elle n’est pas appelée en fonction des yeux du consommateur – elle se trouve à droite d’un opérateur d’affectation.

Cette question pourrait probablement être étendue pour inclure tous les types de validation de données effectués dans les configurateurs de propriétés, mais je suis particulièrement intéressé par le cas ci-dessus.

Consultez mscorlib.dll avec Reflector, dans une situation similaire telle que System.Ssortingng.SsortingngBuilder.Capacity Microsoft utilise ArgumentOutOfRangeException () similaire à:

 public int PropertyA { get { return //etc... } set { if (condition == true) { throw new ArgumentOutOfRangeException("value", "/* etc... */"); } // ... etc } } 

Pour moi, ArgumentException (ou un enfant) a plus de sens, car l’argument (valeur) que vous avez fourni n’est pas valide, et c’est pour cette raison que ArgumentException a été créé.

Je ne lancerais aucune exception. Plutôt, j’autoriserais une chaîne de n’importe quelle longueur et j’aurais ensuite une méthode séparée “Validate” sur la classe appelée avant l’enregistrement. Il existe un certain nombre de scénarios, en particulier si vous utilisez la liaison de données dans laquelle la levée d’exceptions à partir des règles de propriété peut vous mettre dans le pésortingn.

Le problème avec le fait de jeter des exceptions aux créateurs de propriété est que les programmeurs oublient de les attraper. Cela dépend en quelque sorte du degré de propreté auquel vous vous attendez. Dans ce cas, je m’attendrais à ce que les longueurs de chaîne longues soient communes, et non exceptionnelles, et que l’utilisation d’une exception serait un “contrôle de stream avec des exceptions”.

Pour citer les directives de conception de Microsoft pour les bibliothèques de classes en développement :

N’utilisez pas d’exceptions pour un stream de contrôle normal, si possible. À l’exception des défaillances du système et des opérations avec des conditions de concurrence potentielles, les concepteurs de framework doivent concevoir des API afin que les utilisateurs puissent écrire du code sans exception. Par exemple, vous pouvez fournir un moyen de vérifier les conditions préalables avant d’appeler un membre afin que les utilisateurs puissent écrire du code qui ne génère pas d’exceptions.

Rappelez-vous combien de problèmes en informatique sont résolus en ajoutant un niveau supplémentaire d’indirection?

Une approche serait de créer un nouveau type, FixedLengthSsortingng, par exemple. Ce sont des instances de ce type qui valident les longueurs de chaînes avec lesquelles elles sont initialisées – avec un opérateur de conversion qui effectue la conversion de type à partir d’une chaîne simple. Si votre paramètre de propriété prend un tel type comme argument, toute violation deviendra une exception de conversion de type au lieu d’une exception d’argument / propriété.

En pratique, je le ferais rarement. Ça sent un peu de prendre OO trop loin – mais dans certains cas, cela peut être une technique utile, donc je le mentionne ici pour être complet.

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

via MSDN

Vous pouvez utiliser InvalidOperationException C’est un compromis. Je ne voudrais pas non plus utiliser une ArgumentException.

Essayez d’utiliser les exceptions existantes autant que possible. Dans ce cas, utilisez InvalidOperationException car la valeur entrante amène l’object dans un état incohérent. Des exceptions personnalisées peuvent être créées lorsqu’une gestion spécifique avec l’exception personnalisée est nécessaire. Dans ce cas, vous ne lancez qu’une exception avec du texte, utilisez donc InvalidOperationException.

Lors du lancement de InvalidOperationException, affichez la valeur transmise à ce setter.