Je veux savoir ce qui est considéré comme le meilleur moyen de revenir quand j'ai une if
déclaration.
Exemple 1:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
else
{
myString = "Name " + myString;
// Do something more here...
return true;
}
}
Exemple 2:
public bool MyFunction()
{
// Get some string for this example
string myString = GetString();
if (myString == null)
{
return false;
}
myString = "Name " + myString;
// Do something more here...
return true;
}
Comme vous pouvez le voir dans les deux exemples, la fonction reviendra, true/false
mais est-ce une bonne idée de mettre une else
déclaration comme dans le premier exemple ou mieux de ne pas la mettre?
else
.Réponses:
L'exemple 2 est connu sous le nom de bloc de garde. Il est plus approprié de renvoyer / jeter une exception tôt si quelque chose ne va pas (paramètre incorrect ou état non valide). En logique normale, il est préférable d'utiliser l'exemple 1
la source
Mon style personnel consiste à utiliser le simple
if
pour les blocs de garde et leif
/else
dans le code de traitement de la méthode.Dans ce cas, vous utilisez la
myString == null
condition de garde, j'aurais donc tendance à utiliser leif
motif simple .Considérons un code un peu plus compliqué:
Exemple 1:
Exemple 2:
Dans l'exemple 1, la protection et le reste de la méthode sont sous la forme
if
/else
. Comparez cela à l'exemple 2, où le bloc de garde est sous laif
forme unique , alors que le reste de la méthode utilise la formeif
/else
. Personnellement, je trouve que l’exemple 2 est plus facile à comprendre, tandis que l’exemple 1 semble désordonné et trop en retrait.Notez qu'il s'agit d'un exemple artificiel et que vous pouvez utiliser des
else if
instructions pour le nettoyer, mais mon objectif est de montrer la différence entre les blocs de garde et le code de traitement de la fonction.Un compilateur décent devrait quand même générer la même sortie pour les deux. La seule raison d'utiliser l'un ou l'autre est la préférence personnelle ou de se conformer au style du code existant.
la source
Personnellement, je préfère la deuxième méthode. J'ai l'impression que c'est plus court, moins indenté et plus facile à lire.
la source
Ma pratique personnelle est la suivante:
Par exemple:
Par exemple:
La règle "une sortie" est également utile lorsque le calcul nécessite des ressources externes que vous devez libérer, ou indique que vous devez réinitialiser avant de quitter la fonction; parfois, ils sont ajoutés plus tard au cours du développement. Avec plusieurs sorties à l'intérieur de l'algorithme, il est beaucoup plus difficile d'étendre correctement toutes les branches. (Et si des exceptions peuvent se produire, la libération / réinitialisation doit également être bloquée, pour éviter les effets secondaires dans de rares cas exceptionnels ...).
Votre cas semble tomber dans la catégorie "sortie rapide avant le vrai travail", et je l'écrirais comme votre version de l'exemple 2.
la source
Je préfère utiliser des gardes partout où je peux pour deux raisons:
De manière générale, je préfère voir des méthodes où la fonctionnalité principale de la méthode est claire et minimale. Les blocs de garde aident à rendre cela visuel.
la source
J'aime l'approche "Fall Through":
L'action a une condition spécifique, tout le reste n'est que le retour par défaut «échec».
la source
Si j'ai une seule condition, je ne passerais pas trop de temps à méditer sur le style. Mais si j'ai plusieurs conditions de garde, je préférerais style2
Picuture cela. Supposons que les tests sont complexes et que vous ne voulez vraiment pas les lier dans une seule condition if-ORed pour éviter toute complexité:
contre
Ici, il y a deux avantages principaux
Vous séparez le code d’une seule fonction en deux blocs visuels: un bloc supérieur de validations (conditions de garde) et un bloc inférieur de code exécutable.
Si vous devez ajouter / supprimer une condition, vous réduisez vos chances de tout gâcher dans l’échelle if-elseif-else.
Un autre avantage mineur est que vous avez une paire d’accolades de moins à entretenir.
la source
Cela devrait être une question qui sonne mieux.
s'exprime mieux alors
pour les petites méthodes, cela ne fera pas beaucoup de différence, mais pour les grandes méthodes composées, cela peut rendre la compréhension plus difficile, car elle ne sera pas correctement séparée
la source
do something
incluent une déclaration. Sinon, le second code s'exécuterado somethingelse
quel que soit leif
prédicat qui ne correspond pas au fonctionnement du premier bloc.Je trouve l'exemple 1 irritant, car l'instruction return manquante à la fin d'une fonction renvoyant une valeur déclenche immédiatement le signe "Attendez, il y a quelque chose qui ne va pas". Donc, dans des cas comme celui-ci, je choisirais l'exemple 2.
Cependant, il y a généralement plus d'implication, en fonction du but de la fonction, par exemple la gestion des erreurs, la journalisation, etc. Je suis donc avec la réponse de Lorand Kedves à ce sujet, et j'ai généralement un point de sortie à la fin, même au prix coûtant. d'une variable de drapeau supplémentaire. Cela facilite la maintenance et les extensions ultérieures dans la plupart des cas.
la source
Lorsque votre
if
instruction revient toujours, il n'y a aucune raison d'utiliser une autre option pour le code restant dans la fonction. Cela ajoute des lignes et une indentation supplémentaires. L'ajout de code inutile rend la lecture plus difficile et, comme tout le monde le sait, la lecture du code est difficile .la source
Dans votre exemple, le
else
est évidemment inutile, MAIS ...Lorsque vous parcourez rapidement les lignes de code, vos yeux se penchent généralement sur les accolades et les empreintes pour vous faire une idée du flux de code. avant qu'ils ne s'installent réellement sur le code lui-même. Par conséquent, écrire le
else
, et mettre des accolades et une indentation autour du second bloc de code permet au lecteur de voir plus rapidement qu'il s'agit d'une situation "A ou B", dans laquelle l'un ou l'autre bloc sera exécuté. C'est-à-dire que le lecteur voit les accolades et l'indentation AVANT de voirreturn
après l'initialeif
.À mon avis, il s’agit d’un des rares cas où l’ajout d’un élément redondant au code le rend PLUS lisible, pas moins.
la source
Je préférerais l'exemple 2, car il est immédiatement évident que la fonction retourne quelque chose . Mais même plus que cela, je préférerais revenir d'un endroit, comme ceci:
Avec ce style je peux:
Voyez tout de suite que je retourne quelque chose.
Saisir le résultat de chaque appel de la fonction avec un seul point d'arrêt.
la source
Mon style personnel a tendance à aller
Utilisez les
else
instructions commentées pour indiquer le déroulement du programme et le garder lisible, tout en évitant les retraits massifs qui peuvent facilement atteindre l'écran si de nombreuses étapes sont impliquées.la source
else
clauses incluses, je choisirais ce dernier parce que le compilateur les ignorera également. Cela dépendelse if
toutefois du fait que l'indentation n'augmente pas davantage que l'original une fois, sinon , je serais d'accord avec vous. Mais mon choix serait de laisser tomberelse
complètement si ce style était autorisé.Je souhaiterai écrire
Je préfère ce style car il est évident que j'y retournerais
userName != null
.la source
myString
résultat non utilisé . Je viens de copier la fonction de OP. Je vais le changer pour quelque chose qui ressemble plus à la vie réelle. Le test booléen est trivial et ne devrait pas être un problème.Ma règle générale est soit de faire un if-return sans autre (surtout des erreurs), soit de faire une chaîne complète if-else-if sur toutes les possibilités.
De cette façon, j'évite d'essayer d'être trop sophistiqué avec mes branches, car chaque fois que je finis par le faire, je code la logique d'application dans mes ifs, ce qui les rend plus difficiles à gérer (par exemple, si un enum OK ou ERR et que j'écris tous mes profitant du fait que! OK <-> ERR, il devient très pénible d’ajouter une troisième option à l’énum prochain.)
Dans votre cas, par exemple, j'utiliserais un simple if, puisque "return if null" est sûr d'être un modèle courant et qu'il est peu probable que vous ayez à vous soucier d'une troisième possibilité (en plus de null / non null) A l'avenir.
Cependant, si le test était quelque chose qui a fait une inspection plus approfondie sur les données, je serais plutôt orienté vers une analyse complète si-sinon.
la source
Je pense que l'exemple 2 présente de nombreux pièges qui pourraient éventuellement conduire à un code non souhaité. Le premier objectif est basé sur la logique entourant la variable "myString". Par conséquent, pour être explicite, tous les tests de conditions doivent avoir lieu dans un bloc de code tenant compte de la logique connue et par défaut / inconnue .
Et si par la suite le code était introduit involontairement dans l'exemple 2 qui modifiait la sortie de manière significative:
Je pense qu'avec le
else
bloc qui suivait immédiatement la recherche de null, les programmeurs ayant ajouté les améliorations aux versions futures ajouteraient toute la logique, car nous avons maintenant une chaîne de logique qui n'était pas voulue pour la règle d'origine (retour si la valeur est nul).Je crois profondément en cela à certaines des directives C # sur Codeplex (lien vers celui-ci ici: http://csharpguidelines.codeplex.com/ ) qui indiquent ce qui suit:
"Ajoute un commentaire descriptif si le bloc par défaut (else) est supposé être vide. De plus, si ce bloc n’est pas censé être atteint, lève une exception InvalidOperationException pour détecter les modifications futures susceptibles de tomber dans les cas existants. Cela garantit un meilleur code, car tous les chemins que le code peut emprunter ont été pensés. "
Je pense que la bonne pratique de programmation lors de l’utilisation de blocs logiques comme celui-ci consiste à toujours ajouter un bloc par défaut (if-else, case: default) afin de comptabiliser explicitement tous les chemins de code et de ne pas laisser le code ouvert à des conséquences logiques non voulues.
la source
myString
valeur et le code qui succède auif
bloc est la logique résultante si la chaîne! = Null. Par conséquent, puisque l’accent est mis sur la logique supplémentaire manipulant cette valeur spécifique , je pense qu’elle devrait être encapsulée dans unelse
bloc. Autrement, cela ouvre un potentiel, comme je l’ai montré plus tôt, pour séparer involontairement la logique et introduire des conséquences inattendues. Cela n'arrivera peut-être pas tout le temps, mais c'était vraiment une question de style d'opinion basée sur les meilleures pratiques .