Avantages de l’utilisation de l’opérateur conditionnel: (ternaire)

Quels sont les avantages et les inconvénients de l’opérateur?: Par opposition à l’instruction if-else standard. Les plus évidentes étant:

Conditionnel: opérateur

  • Plus court et plus concis en matière de comparaisons de valeurs directes et d’affectations
  • Ne semble pas être aussi flexible que la construction if / else

Standard If / Else

  • Peut être appliqué à d’autres situations (comme les appels de fonctions)
  • Sont souvent inutilement longs

La lisibilité semble varier pour chacun en fonction de la déclaration. Peu de temps après avoir été exposé à l’opérateur?: Il m’a fallu du temps pour digérer exactement comment cela fonctionnait. Recommanderiez-vous de l’utiliser dans la mesure du possible ou de vous en tenir si / autrement étant donné que je travaille avec de nombreux non-programmeurs?

Je recommande essentiellement de ne l’utiliser que lorsque la déclaration résultante est extrêmement courte et représente une augmentation significative de la concision sur l’équivalent if / else sans sacrifier la lisibilité.

Bon exemple:

 int result = Check() ? 1 : 0; 

Mauvais exemple:

 int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0; 

Ceci est à peu près couvert par les autres réponses, mais “c’est une expression” n’explique pas vraiment pourquoi c’est si utile …

Dans des langages tels que C ++ et C #, vous pouvez définir des champs locaux en lecture seule (dans un corps de méthode) en les utilisant. Cela n’est pas possible avec une instruction if / then conventionnelle car la valeur d’un champ readonly doit être affectée dans cette seule déclaration:

 readonly int speed = (shiftKeyDown) ? 10 : 1; 

n’est pas la même chose que:

 readonly int speed; if (shifKeyDown) speed = 10; // error - can't assign to a readonly else speed = 1; // error 

De la même manière, vous pouvez intégrer une expression tertiaire dans un autre code. En plus de rendre le code source plus compact (et dans certains cas plus lisible en conséquence), il peut également rendre le code machine généré plus compact et plus efficace:

 MoveCar((shiftKeyDown) ? 10 : 1); 

… peut générer moins de code que d’appeler deux fois la même méthode:

 if (shiftKeyDown) MoveCar(10); else MoveCar(1); 

Bien sûr, c’est aussi une forme plus pratique et concise (moins de frappe, moins de répétitions et peut réduire le risque d’erreurs si vous devez dupliquer des morceaux de code dans un if / else). Dans les cas propres “pattern commun” comme ceci:

 object thing = (reference == null) ? null : reference.Thing; 

… il est tout simplement plus rapide de lire / parsingr / comprendre (une fois que vous y êtes habitué) que son équivalent si / sinon long, de sorte qu’il peut vous aider à accélérer le code.

Bien sûr, le fait que ce soit utile ne signifie pas que c’est la meilleure chose à utiliser dans tous les cas. Je vous conseille de ne l’utiliser que pour de petits bouts de code où la signification est claire (ou plus claire) en utilisant ?: – si vous l’utilisez dans un code plus complexe, ou des opérateurs ternaires nesteds lire.

Je trouve cela particulièrement utile lors du développement web si je souhaite définir une variable sur une valeur envoyée dans la requête si elle est définie ou sur une valeur par défaut si ce n’est pas le cas.

Je choisis généralement un opérateur ternaire lorsque j’aurais beaucoup de code en double.

 if (a > 0) answer = compute(a, b, c, d, e); else answer = compute(-a, b, c, d, e); 

Avec un opérateur ternaire, ceci pourrait être accompli avec les éléments suivants.

 answer = compute(a > 0 ? a : -a, b, c, d, e); 

Une utilisation vraiment cool est:

 x = foo ? 1 : bar ? 2 : baz ? 3 : 4; 

L’opérateur conditionnel est idéal pour les conditions courtes, comme ceci:

 varA = boolB ? valC : valD; 

Je l’utilise de temps en temps parce que cela prend moins de temps pour écrire quelque chose de cette manière … malheureusement, cette twig peut parfois être manquée par un autre développeur parcourant votre code. De plus, le code n’est généralement pas si court, alors j’aide généralement à le rendre lisible en le mettant? et: sur des lignes séparées, comme ceci:

 doSomeStuffToSomething(shouldSomethingBeDone() ? getTheThingThatNeedsStuffDone() : getTheOtherThingThatNeedsStuffDone()); 

Cependant, le gros avantage de l’utilisation des blocs if / else (et pourquoi je les préfère) est qu’il est plus facile de venir plus tard et d’append une logique supplémentaire à la twig,

 if (shouldSomethingBeDone()) { doSomeStuffToSomething(getTheThingThatNeedsStuffDone()); doSomeAdditionalStuff(); } else { doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone()); } 

ou append une autre condition:

 if (shouldSomethingBeDone()) { doSomeStuffToSomething(getTheThingThatNeedsStuffDone()); doSomeAdditionalStuff(); } else if (shouldThisOtherThingBeDone()){ doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone()); } 

Donc, en fin de compte, il s’agit de commodité pour vous (plus courte à utiliser:?) Que de commodité pour vous (et les autres) plus tard. C’est un appel au jugement … mais comme tous les autres problèmes de mise en forme du code, la seule règle est d’être cohérent et d’être visuellement courtois envers ceux qui doivent maintenir (ou noter!) Votre code.

(tout code compilé avec des yeux)

Une chose à reconnaître en utilisant l’opérateur ternaire est qu’il s’agit d’une expression et non d’une déclaration.

Dans les langages fonctionnels comme le schéma, la distinction n’existe pas:

(si (> ab) ab)

Conditionnel: Opérateur “Ne semble pas être aussi flexible que la construction if / else”

Dans les langages fonctionnels c’est.

Lors de la programmation en langages impératifs, j’applique l’opérateur ternaire dans des situations où j’utiliserais généralement des expressions (affectation, instructions conditionnelles, etc.).

Bien que les réponses ci-dessus soient valables, et je suis d’accord avec la lisibilité étant importante, il y a 2 autres points à considérer:

  1. En C # 6, vous pouvez avoir des méthodes utilisant des expressions.

Cela rend particulièrement concis d’utiliser le ternaire:

 ssortingng GetDrink(DayOfWeek day) => day == DayOfWeek.Friday ? "Beer" : "Tea"; 
  1. Le comportement diffère en ce qui concerne la conversion de type implicite.

Si vous avez les types T1 et T2 qui peuvent être tous les deux implicitement convertis en T , alors ce qui suit ne fonctionne pas :

 T GetT() => true ? new T1() : new T2(); 

(car le compilateur essaie de déterminer le type de l’expression ternaire et qu’il n’y a pas de conversion entre T1 et T2 .)

En revanche, la version if/else ci-dessous fonctionne:

 T GetT() { if (true) return new T1(); return new T2(); } 

car T1 est converti en T et T2

Parfois, il peut être plus facile de lire l’affectation d’une valeur bool à première vue:

 // With button.IsEnabled = someControl.HasError ? false : true; // Without button.IsEnabled = !someControl.HasError; 

Si je mets une valeur et que je sais que ce sera toujours une ligne de code, j’utilise généralement l’opérateur ternaire (conditionnel). S’il y a une chance que mon code et ma logique changent à l’avenir, j’utilise un if / else car c’est plus clair pour les autres programmeurs.

Vous pourriez aussi être intéressé par le ?? opérateur .

L’avantage de l’opérateur conditionnel est qu’il s’agit d’un opérateur. En d’autres termes, il renvoie une valeur. Puisque if est une instruction, il ne peut pas renvoyer de valeur.

Je recommanderais de limiter l’utilisation de l’opérateur ternaire (? 🙂 à la logique simple d’affectation de ligne simple si / sinon. Quelque chose qui ressemble à ce modèle:

 if() {  = ; } else {  = ; } 

Pourrait être facilement converti en:

  =  ?  : ; 

J’éviterais d’utiliser l’opérateur ternaire dans des situations nécessitant if / else if / else, nested if / else, ou si / else, la logique de twig qui entraîne l’évaluation de plusieurs lignes. Appliquer l’opérateur ternaire dans ces situations entraînerait probablement un code illisible, déroutant et ingérable. J’espère que cela t’aides.

Il y a un avantage de performance à utiliser le? opérateur par exemple. MS Visual C ++, mais c’est vraiment une chose spécifique au compilateur. Le compilateur peut en fait optimiser la twig conditionnelle dans certains cas.

Le scénario dans lequel je l’utilise le plus est celui des valeurs par défaut et surtout des retours.

 return someIndex < maxIndex ? someIndex : maxIndex; 

Ce sont vraiment les seuls endroits que je trouve agréables, mais pour eux je le fais.

Bien que si vous cherchez un booléen, cela peut parfois sembler une chose à faire:

 bool hey = whatever < whatever_else ? true : false; 

Parce que c'est si facile à lire et à comprendre, mais cette idée doit toujours être considérée comme la plus évidente:

 bool hey = (whatever < whatever_else); 

Si vous avez besoin de plusieurs twigs dans les mêmes conditions, utilisez un si:

 if (A == 6) f(1, 2, 3); else f(4, 5, 6); 

Si vous avez besoin de plusieurs twigs avec des conditions différentes, alors si le nombre de déclarations fait boule de neige, vous voudrez utiliser le ternaire:

 f( (A == 6)? 1: 4, (B == 6)? 2: 5, (C == 6)? 3: 6 ); 

En outre, vous pouvez utiliser l’opérateur ternaire lors de l’initialisation.

 const int i = (A == 6)? 1 : 4; 

Faire cela avec if est très désordonné:

 int i_temp; if (A == 6) i_temp = 1; else i_temp = 4; const int i = i_temp; 

Vous ne pouvez pas mettre l’initialisation à l’intérieur du if / else, car cela change la scope. Mais les références et les variables const ne peuvent être liées qu’à l’initialisation.

L’opérateur ternaire peut être inclus dans une valeur alors qu’un if-then-else ne peut pas; d’autre part, un if-then-else peut exécuter des boucles et d’autres instructions, tandis que l’opérateur ternaire ne peut qu’exécuter (éventuellement des valeurs vides) des valeurs.

Sur une note connexe, les && et || les opérateurs autorisent certains modèles d’exécution plus difficiles à implémenter avec if-then-else. Par exemple, si l’on a plusieurs fonctions à appeler et que l’on souhaite exécuter un morceau de code en cas d’échec, cela peut être fait avec l’aide de l’opérateur &&. Le faire sans cet opérateur nécessitera un code redondant, un goto ou une variable de drapeau supplémentaire.

Avec C # 7 , vous pouvez utiliser la nouvelle fonctionnalité ref Locals pour simplifier l’affectation conditionnelle des variables compatibles avec ref. Alors maintenant, non seulement vous pouvez faire:

 int i = 0; T b = default(T), c = default(T); // initialization of C#7 'ref-local' variable using a conditional r-value⁽¹⁾ ref T a = ref (i == 0 ? ref b : ref c); 

… mais aussi l’extrêmement merveilleux:

 // assignment of l-value⁽²⁾ conditioned by C#7 'ref-locals' (i == 0 ? ref b : ref c) = a; 

Cette ligne de code assigne la valeur de a à b ou c , en fonction de la valeur de i .


Remarques
1. r-value est le côté droit d’une affectation, la valeur qui est atsortingbuée.
2. l-value est le côté gauche d’une affectation, la variable qui reçoit la valeur affectée.