Oui, il y a de bonnes raisons :
- Il identifie exactement ce qui est nul, ce qui peut ne pas être évident à partir d'une analyse de la situation.
NullReferenceException
- Cela fait échouer le code en cas d'entrée invalide, même si une autre condition signifie que la valeur n'est pas déréférencée.
- Il fait en sorte que l'exception se produise avant la méthode pourrait avoir d'autres effets secondaires que vous pourriez atteindre avant la première déréférence.
- Cela signifie que vous pouvez être sûr que si vous passez le paramètre dans quelque chose d'autre, vous ne violez pas leur contrat
- Il documente les exigences de votre méthode (en utilisant Contrats de code est encore meilleur pour cela, bien sûr)
Maintenant, pour ce qui est de vos objections :
-
C'est plus lent : Avez-vous trouvé cela pour en fait est le goulot d'étranglement dans votre code, ou vous devinez ? Les contrôles de nullité sont très rapides, et dans la grande majorité des cas, ils ne sont pas nécessaires. no va être le goulot d'étranglement
-
Cela rend le code plus difficile à maintenir : Je pense le contraire. Je pense que c'est plus facile d'utiliser un code où il est clairement indiqué si un paramètre peut être nul ou non, et où vous êtes sûr que cette condition est respectée.
Et pour votre affirmation :
Évidemment, le code qui utilise s lèvera une exception de toute façon.
Vraiment ? Réfléchissez :
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
Cela utilise s
mais il ne lève pas d'exception. Si c'est invalide pour s
est nulle, et que cela indique que quelque chose ne va pas, une exception est le comportement le plus approprié ici.
Maintenant où que vous placez ces contrôles de validation des arguments est une autre question. Vous pouvez décider de faire confiance à tout le code de votre propre classe, et donc de ne pas vous préoccuper des méthodes privées. Vous pouvez décider de faire confiance au reste de votre assemblage, et donc de ne pas vous préoccuper des méthodes internes. Vous devriez presque certainement valider les arguments des méthodes publiques.
Remarque : la surcharge du constructeur à paramètre unique de l'option ArgumentNullException
devrait juste être le nom du paramètre, donc votre test devrait être :
if (s == null)
{
throw new ArgumentNullException("s");
}
Alternativement, vous pouvez créer une méthode d'extension, permettant de terser quelque peu :
s.ThrowIfNull("s");
Dans ma version de la méthode d'extension (générique), je fais en sorte qu'elle renvoie la valeur originale si elle n'est pas nulle, ce qui vous permet d'écrire des choses comme :
this.name = name.ThrowIfNull("name");
Vous pouvez également avoir une surcharge qui ne prend pas le nom du paramètre, si cela ne vous dérange pas trop.
13 votes
Je doute sérieusement qu'une simple vérification des nullités ralentisse votre code de manière significative (ou même mesurable).
0 votes
Eh bien, cela dépend de ce que fait "Use s". Si tout ce qu'il fait est "return s.SomeField", alors la vérification supplémentaire ralentira probablement la méthode d'un ordre de grandeur.
11 votes
Probablement ? Probablement n'est pas suffisant à mes yeux. Où sont vos données de test ? Et quelle est la probabilité qu'un tel changement soit le goulot d'étranglement de votre application en premier lieu ?
0 votes
@Jon : vous avez raison, je n'ai pas de données concrètes ici. Si vous développez pour Windows Phone ou Xbox où le JIT inlining sera affecté par ce "if" supplémentaire, et où le branching est très coûteux, vous pouvez devenir assez paranoïaque.
3 votes
@kaalus : Ajustez donc votre style de code dans ces cas très spécifiques. après avoir prouvé que cela fait une différence significative ou utiliser Debug.Assert (encore une fois, uniquement dans ces situations, voir la réponse d'Eric) pour que les vérifications ne soient activées que dans certaines constructions.
0 votes
Pour ajouter au "doute sérieux" :-) du premier commentateur, une optimisation typique du compilateur consiste à éliminer une vérification implicite de nullité si (l'analyse du flux de données montre) il existe une vérification de nullité précédente. Par conséquent, il arrive très souvent que l'insertion d'une vérification explicite des nullités n'ajoute aucun temps d'exécution. Même si ce n'est pas le cas, un processeur super-scalaire moderne typique est susceptible d'être capable d'exécuter la vérification en un temps effectivement nul, car il peut exécuter la vérification en parallèle avec d'autres activités.