Je vais être impopulaire et dire oui, c'est une mauvaise pratique. SI la fonctionnalité de votre code repose sur celui-ci pour implémenter une logique conditionnelle.
c'est à dire
if(quickLogicA && slowLogicB) {doSomething();}
c'est bien, mais
if(logicA && doSomething()) {andAlsoDoSomethingElse();}
est mauvais, et sûrement personne ne serait d'accord avec?!
if(doSomething() || somethingElseIfItFailed() && anotherThingIfEitherWorked() & andAlwaysThisThing())
{/* do nothing */}
Raisonnement:
Votre code est erroné si les deux côtés sont évalués plutôt que de ne pas exécuter la logique. Il a été avancé que ce n’était pas un problème, l’opérateur 'et' étant défini en c #, le sens est clair. Cependant, je soutiens que ce n'est pas vrai.
Raison 1. Historique
Vous utilisez essentiellement (ce qui était initialement prévu) une optimisation de compilateur pour fournir des fonctionnalités dans votre code.
Bien qu'en c #, la spécification du langage garantisse le court-circuit des opérateurs booléen 'et'. Ce n'est pas le cas de toutes les langues et de tous les compilateurs.
wikipeda répertorie diverses langues et leur approche du court-circuit http://en.wikipedia.org/wiki/Short-circuit_evaluation car il existe de nombreuses approches. Et quelques problèmes supplémentaires dans lesquels je n'entre pas ici.
En particulier, FORTRAN, Pascal et Delphi ont des drapeaux de compilateur qui permettent de basculer ce comportement.
Par conséquent: vous constaterez que votre code fonctionne lors de la compilation, mais pas pour le débogage ou avec un compilateur de remplacement, etc.
Raison 2. Différences de langue
Comme vous pouvez le constater sur wikipedia, toutes les langues n’adoptent pas la même approche du court-circuit, même quand elles spécifient comment les opérateurs booléens doivent le gérer.
En particulier, l'opérateur 'et' de VB.Net ne court-circuite pas et TSQL présente certaines particularités.
Etant donné qu'une "solution" moderne est susceptible d'inclure un certain nombre de langages, tels que javascript, regex, xpath, etc., vous devez en tenir compte lorsque vous clarifiez les fonctionnalités de votre code.
Raison 3. Différences au sein d'une langue
Par exemple, VB en ligne si se comporte différemment de son if. Encore une fois, dans les applications modernes, votre code peut se déplacer entre, par exemple, le code en arrière et un formulaire Web en ligne, vous devez être conscient des différences de signification.
Raison 4. Votre exemple spécifique de vérification de null le paramètre d'une fonction
C'est un très bon exemple. En cela, c’est quelque chose que tout le monde fait, mais c’est en fait une mauvaise pratique à y penser.
Il est très courant de voir ce type de vérification car cela réduit considérablement vos lignes de code. Je doute que quiconque puisse en parler lors d'une révision du code. (et évidemment d'après les commentaires et notes que vous pouvez voir c'est populaire!)
Cependant, cela ne tient pas compte des meilleures pratiques pour plus d'une raison!
Son très clair de nombreuses sources, que les meilleures pratiques est de vérifier vos paramètres de validité avant de les utiliser et de lancer une exception si elles ne sont pas valides. Votre extrait de code ne montre pas le code environnant, mais vous devriez probablement faire quelque chose comme:
if (smartphone == null)
{
//throw an exception
}
// perform functionality
Vous appelez une fonction à partir de l'instruction conditionnelle. Bien que le nom de votre fonction implique qu'il calcule simplement une valeur, il peut masquer les effets secondaires. par exemple
Smartphone.GetSignal() { this.signal++; return this.signal; }
else if (smartphone.GetSignal() < 1)
{
// Do stuff
}
else if (smartphone.GetSignal() < 2)
{
// Do stuff
}
la meilleure pratique suggérerait:
var s = smartphone.GetSignal();
if(s < 50)
{
//do something
}
Si vous appliquez ces meilleures pratiques à votre code, vous pouvez constater que votre possibilité de réaliser un code plus court grâce à l'utilisation de la condition cachée disparaît. La meilleure pratique est de faire quelque chose , de gérer le cas où le smartphone est nul.
Je pense que vous constaterez que c'est également le cas pour d'autres usages courants. Vous devez vous rappeler que nous avons aussi:
conditionnels en ligne
var s = smartphone!=null ? smartphone.GetSignal() : 0;
et coalescence nulle
var s = smartphoneConnectionStatus ?? "No Connection";
qui fournissent des fonctionnalités similaires de longueur de code court avec plus de clarté
nombreux liens pour supporter tous mes points:
https://stackoverflow.com/questions/1158614/what-is-the-best-practice-in-case-one-argument-is-null
Validation des paramètres de constructeur en C # - Meilleures pratiques
Faut-il vérifier la valeur null s'il ne s'attend pas à la valeur null?
https://msdn.microsoft.com/en-us/library/seyhszts%28v=vs.110%29.aspx
https://stackoverflow.com/questions/1445867/why-would-a-language-not-use-short-circuit-evaluation
http://orcharddojo.net/orchard-resources/Library/DevelopmentGuidelines/BestPractices/CSharp
exemples de drapeaux de compilation qui affectent les courts-circuits:
Fortran: "sce | nosce Par défaut, le compilateur évalue les courts-circuits dans certaines expressions logiques à l'aide de règles XL Fortran. La spécification de sce permet au compilateur d'utiliser des règles Fortran non-XL. Le compilateur procédera à une évaluation des courts-circuits si les règles actuelles le permettent. La valeur par défaut est nosce. "
Pascal: "B - Une directive d'indicateur qui contrôle l'évaluation des courts-circuits. Voir Ordre d'évaluation des opérandes d'opérateurs dyadiques pour plus d'informations sur l'évaluation des courts-circuits. Voir aussi l'option de compilation -sc du compilateur en ligne de commande pour plus d'informations ( documenté dans le manuel d'utilisation). "
Delphi: "Delphi prend en charge l'évaluation des courts-circuits par défaut. Elle peut être désactivée à l'aide de la directive de compilation {$ BOOLEVAL OFF}."