Considérez une situation dans laquelle vous devez appeler des routines successives et que vous vous arrêtez dès que l'on rend une valeur qui pourrait être évaluée comme positive (véritable, objet, 1, str (1)).
C'est très tentant de faire Ceci: P>
fruit = getOrange();
if(!fruit){
fruit = getApple();
if(!fruit){
fruit = getMango();
if(!fruit){
fruit = new Banana();
}
}
}
return fruit;
7 Réponses :
Le problème, comme je le vois, n'est pas la structure, mais les règles de conduite. Pourquoi Getorange vient-il avant que GetApple, etc.
Vous êtes probablement plus susceptible de voir quelque chose de plus axé sur les données: p> et séparément, p> fruit = getOrange() ?? getApple() ?? getMango() ?? new Banana();
Comme l'énumé, car il correspond à la vue du monde existant de l'OP. L'usine de fruits ... Bon Seigneur. On dirait beaucoup de problèmes pour un sac de fruits. Mais je comprends pourquoi vous le faites de cette façon.
Vous en supposez beaucoup sur les constructions de langue disponibles que l'OP ne met pas dans sa question.
En outre, il n'y a aucune raison d'assumer sa langue, ni d'autre, a l'opérateur de coalesce. Je connais seulement C #, et ce n'est certainement pas C #, probablement c'est PHP. C # ne permettra pas l'affectation à l'intérieur d'un si conditionnel.
Votre première implémentation suppose que la fonction est une usine. J'ai choisi des fruits parce que j'ai faim guichet automatique. En réalité, cela pourrait être une liste de processus entièrement différente. L'opérateur de coalesce a l'air cool cependant, ne l'a jamais vu auparavant. Il remplit effectivement cet écart, mais malheureusement pas omniprésent.
Je ne fais aucune hypothèse sur la langue, donnant simplement une vue concise sur la logique que vous souhaitez suivre. Mon point était que je m'attendais à ce que vous faites ici pour avoir une approche plus approfondie et axée sur les données. La plupart des langues modernes ont des opérateurs de coalesse disponibles - les plus âgés ont des méthodes de regroupement. Vous pouvez également en écrire un vous-même assez simplement.
Dans une langue fortement typée qui ne correspond pas à 0 / null à Faux et non-0 / non null à vrai, je dirais que c'est probablement sûr, mais légèrement moins lisible dans le cas général, où votre méthode Les noms et le nombre de paramètres peuvent être plus importants. Je l'éviterais personnellement, à l'exception de certains idiomes standard, dans les cas où 0 / null équivaut à faux et non-0 / non-null à vrai simplement en raison du risque potentiel d'affectation déroulante avec l'égalité en lecture du code. Certaines idiomes dans des langues faiblement typées, comme c, sont tellement omniprésentes qu'il n'a pas de sens de les éviter, .e.g,
Je peux penser à deux alternatives.
Le premier n'est autorisé que dans des langues comme la vôtre (php?), où single = dans un conditionnel est correct. P>
fruit = getOrange();
if(!fruit) fruit = getApple();
if(!fruit) fruit = getMango();
if(!fruit) fruit = new Banana();
Si vous souhaitez une syntaxe succincte, plusieurs langues permettent d'utiliser «logique ou» à cet effet (C # fournit explicitement un opérateur coalfess, car les NULLS ne sont pas fausse).
python: p> c #: p>
Je pense qu'il existe des plans pour les futures versions de PHP pour rendre la deuxième partie des instructions ternaires de style C en option, vous permettant d'utiliser ?: Code> dans php comme C # 'S ?? code> .
La mise en œuvre de Python adapterait JavaScript. L'opérateur coalescent serait un bon ajout de nombreuses langues. Merci pour cela.
Pour répondre directement à votre question: il est généralement em> forme de mauvaise forme pour avoir des effets secondaires dans la déclaration conditionnelle. comme un travail autour, vous pouvez stocker vos constructeurs de fruits dans un tableau et trouver le Premier constructeur qui retourne non-NULL (pseudocode): P> var fruit = constructors
.Select(constructor => constructor())
.Filter(x => x != null)
.First();
en C ou C ++, vous pouvez écrire:
do {
fruit = getOrange();
if (fruit) break;
fruit = getApple();
if (fruit) break;
fruit = getMango();
if (fruit) break;
fruit = new Banana();
} while (false);
Je ne pense pas que personne a mentionné pourtant que la première version peut être une sorte de douleur à traverser dans un débogueur. La différence de lisibilité est discutable, mais en général, j'évite les affectations et les appels de fonctions dans des conditionnels pour faciliter la suivi de l'exécution, si nécessaire (même si je n'ai jamais besoin de le déboguer, quelqu'un d'autre peut avoir besoin de modifier le code plus tard. ). p>