web-dev-qa-db-fra.com

Ternaire ou non ternaire?

Je suis personnellement un défenseur de l'opérateur ternaire: ()? :; Je me rends compte qu'il a sa place, mais j'ai rencontré de nombreux programmeurs qui sont totalement contre de l'utiliser, et certains qui l'utilisent trop souvent.

Quels sont vos sentiments à ce sujet? Quel code intéressant avez-vous vu l'utiliser?

179
pixel

Utilisez-le pour expressions simples uniquement:

int a = (b > 10) ? c : d;

Ne pas enchaîner ou imbriquer opérateurs ternaires car il est difficile à lire et déroutant:

int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;

De plus, lorsque vous utilisez l'opérateur ternaire, envisagez de formater le code de manière à améliorer la lisibilité:

int a = (b > 10) ? some_value                 
                 : another_value;
235
marcospereira

Cela rend le débogage un peu plus difficile car vous ne pouvez pas placer de points d'arrêt sur chacune des sous-expressions. Je l'utilise rarement.

131
David Segonds

Je les aime, surtout dans les langues à caractères sûrs.

Je ne vois pas comment cela:

int count = (condition) ? 1 : 0;

est plus difficile que cela:

int count;

if (condition)
{
  count = 1;
} 
else
{
  count = 0;
}

modifier -

Je dirais que les opérateurs ternaires rendent tout moins complexe et plus net que l'alternative.

80
Ian P

Enchaîné, je vais bien - imbriqué, pas tellement.

J'ai tendance à les utiliser davantage en C simplement b/c, c'est une instruction if qui a de la valeur, donc cela réduit les répétitions ou les variables inutiles:

x = (y < 100) ? "dog" :
    (y < 150) ? "cat" :
    (y < 300) ? "bar" : "baz";

plutôt que

     if (y < 100) { x = "dog"; } 
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; } 
else              { x = "baz"; }

Dans des missions comme celle-ci, je trouve que c'est moins à refactoriser et plus clair.

Quand je travaille en Ruby d'autre part, je suis plus susceptible d'utiliser if...else...end parce que c'est aussi une expression.

x =   if (y < 100) then "dog"
    Elif (y < 150) then "cat"
    Elif (y < 300) then "bar"
    else                "baz"
    end

(bien que, certes, pour quelque chose d'aussi simple, je pourrais simplement utiliser l'opérateur ternaire de toute façon).

41
rampion

L'opérateur ternaire ?: N'est qu'un équivalent fonctionnel de la construction procédurale if. Ainsi, tant que vous n'utilisez pas d'expressions imbriquées ?:, Les arguments pour/contre la représentation fonctionnelle de toute opération s'appliquent ici. Mais l'imbrication des opérations ternaires peut entraîner un code qui prête à confusion (exercice pour le lecteur: essayez d'écrire un analyseur qui gérera les conditions ternaires imbriquées et vous apprécierez leur complexité).

Mais il existe de nombreuses situations où une utilisation prudente de l'opérateur ?: Peut entraîner un code qui est en fait plus facile à lire qu'autrement. Par exemple:

int compareTo(Object object) {
    if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
       return 1;
    if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
       return -1;
    else
      return 0;              
}

Maintenant, comparez cela avec ceci:

int compareTo(Object object) {
    if(isLessThan(object))
        return reverseOrder ? 1 : -1;         
    else(isGreaterThan(object))
        return reverseOrder ? -1 : 1;
    else        
       return 0;              
}

Comme le code est plus compact, il y a moins de bruit syntaxique et en utilisant judicieusement l'opérateur ternaire (c'est seulement en relation avec la propriété reverseOrder) le résultat final n'est pas particulièrement concis.

39
Ryan Delucchi

C'est une question de style, vraiment; les règles subconscientes que j'ai tendance à suivre sont:

  • Évalue seulement 1 expression - donc foo = (bar > baz) ? true : false, mais PAS foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • Si je l'utilise pour la logique d'affichage, par ex. <%= (foo) ? "Yes" : "No" %>
  • Ne l'utilisez vraiment que pour l'affectation; jamais de logique de flux (donc jamais (foo) ? FooIsTrue(foo) : FooIsALie(foo)) La logique des flux en ternaire est elle-même un mensonge, ignorez ce dernier point.

Je l'aime parce qu'il est concis et élégant pour les opérations d'affectation simples.

24
Keith Williams

Comme tant de questions d'opinion, la réponse est inévitablement: cela dépend

Pour quelque chose comme:

return x ? "Yes" : "No";

Je pense que c'est beaucoup plus concis (et plus rapide à analyser) que:

if (x) {
    return "Yes";
} else {
    return "No";
}

Maintenant, si votre expression conditionnelle est complexe, l'opération ternaire n'est pas un bon choix. Quelque chose comme:

x && y && z >= 10 && s.Length == 0 || !foo

n'est pas un bon candidat pour l'opérateur ternaire.

En passant, si vous êtes un programmeur C, GCC a en fait ne extension qui vous permet d'exclure la partie if-true du ternaire, comme ceci:

/* 'y' is a char * */
const char *x = y ? : "Not set";

Ce qui définira x sur y en supposant que y n'est pas NULL. Bon produit.

18
Sean Bright

Dans mon esprit, cela n'a de sens que d'utiliser l'opérateur ternaire dans les cas où une expression est nécessaire.

Dans d'autres cas, il semble que l'opérateur ternaire diminue la clarté.

12
John Mulder

Par la mesure de complexité cyclomatique , l'utilisation des instructions if ou de l'opérateur ternaire sont équivalentes. Donc, par cette mesure, la réponse est non , la complexité serait exactement la même qu'auparavant.

Par d'autres mesures telles que la lisibilité, la maintenabilité et DRY (Don't-Repeat-Yourself)), chaque choix peut s'avérer meilleur que l'autre.

11
Greg Hewgill

Je l'utilise assez souvent dans des endroits où je suis contraint de travailler dans un constructeur - par exemple, les nouvelles constructions .NET 3.5 LINQ to XML - pour définir des valeurs par défaut lorsqu'un paramètre facultatif est nul.

Exemple artificiel:

var e = new XElement("Something",
    param == null ? new XElement("Value", "Default")
                  : new XElement("Value", param.ToString())
);

ou (merci astérite)

var e = new XElement("Something",
    new XElement("Value",
        param == null ? "Default"
                      : param.ToString()
    )
);

Que vous utilisiez ou non l'opérateur ternaire, il est important de vous assurer que votre code est lisible. Toute construction peut être rendue illisible.

10
Erik Forbes

J'utilise l'opérateur ternaire partout où je peux, sauf si cela rend le code extrêmement difficile à lire, mais c'est généralement juste une indication que mon code pourrait utiliser un peu de refactoring.

Cela m'étonne toujours de voir comment certaines personnes pensent que l'opérateur ternaire est une caractéristique "cachée" ou quelque peu mystérieuse. C'est l'une des premières choses que j'ai apprises lorsque je commence à programmer en C, et je ne pense pas que cela diminue la lisibilité du tout. C'est une partie naturelle de la langue.

9
ilitirit

(Hack du jour)

#define IF(x) x ?
#define ELSE :

Ensuite, vous pouvez faire if-then-else comme expression:

int b = IF(condition1)    res1
        ELSE IF(condition2)  res2
        ELSE IF(conditions3) res3
        ELSE res4;
7
John John

Je suis d'accord avec jmulder: il ne doit pas être utilisé à la place d'un if, mais il a sa place pour l'expression de retour ou à l'intérieur d'une expression:

echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;

Le premier n'est qu'un exemple, un meilleur support i18n du pluriel devrait être utilisé!

7
PhiLho

Si vous utilisez l'opérateur ternaire pour une affectation conditionnelle simple, je pense que ça va. Je l'ai vu (ab) utilisé pour contrôler le déroulement du programme sans même faire une affectation, et je pense que cela devrait être évité. Utilisez une instruction if dans ces cas.

6
Bill the Lizard

Je les aime. Je ne sais pas pourquoi, mais je me sens très cool quand j'utilise l'expression ternaire.

5
JimDaniel

J'ai vu de telles bêtes comme (c'était en fait bien pire car c'était isValidDate et vérifié mois et jour aussi, mais je ne pouvais pas être dérangé d'essayer de me souvenir de tout):

isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

où, clairement, une série d'instructions if aurait été meilleure (bien que celle-ci soit toujours meilleure que la version macro que j'ai vue).

Cela ne me dérange pas pour de petites choses comme:

reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;

ou même des choses un peu délicates comme:

printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");
5
paxdiablo

Je pense que l'opérateur ternaire devrait être utilisé en cas de besoin. C'est évidemment un choix très subjectif, mais je trouve qu'une expression simple (spécialement comme expression de retour) est beaucoup plus claire qu'un test complet. Exemple en C/C++:

return (a>0)?a:0;

Par rapport à:

if(a>0) return a;
else return 0;

Vous avez également le cas où la solution se situe entre l'opérateur ternaire et la création d'une fonction. Par exemple en Python:

l = [ i if i > 0 else 0 for i in lst ]

L'alternative est:

def cap(value):
    if value > 0:
        return value
    return 0
l = [ cap(i) for i in lst ]

Il est suffisamment nécessaire qu'en Python (à titre d'exemple), un tel idiome puisse être vu régulièrement:

l = [ ((i>0 and [i]) or [0])[0] for i in lst ]

cette ligne utilise les propriétés des opérateurs logiques en Python: ils sont paresseux et retourne la dernière valeur calculée si elle est égale à l'état final.

5
PierreBdR

Je n'utilise presque jamais l'opérateur ternaire parce que chaque fois que je l'utilise, cela me fait toujours penser beaucoup plus que je ne dois le faire plus tard lorsque j'essaye de le maintenir.

J'aime éviter la verbosité, mais quand cela rend le code beaucoup plus facile à saisir, je vais opter pour la verbosité.

Considérer:

String name = firstName;

if (middleName != null) {
    name += " " + middleName;
}

name += " " + lastName;

Maintenant, c'est un peu verbeux, mais je le trouve beaucoup plus lisible que:

String name = firstName + (middleName == null ? "" : " " + middleName)
    + " " + lastName;

ou:

String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;

Il semble simplement compresser trop d'informations dans trop peu d'espace, sans préciser ce qui se passe. Chaque fois que je vois un opérateur ternaire utilisé, j'ai toujours trouvé une alternative qui semblait beaucoup plus facile à lire ... là encore, c'est une opinion extrêmement subjective, donc si vous et vos collègues trouvez le ternaire très lisible, allez-y.

4
Mike Stone

J'aime utiliser l'opérateur dans le code de débogage pour imprimer les valeurs d'erreur, donc je n'ai pas à les rechercher tout le temps. Habituellement, je fais cela pour les impressions de débogage qui ne resteront pas une fois le développement terminé.

int result = do_something();
if( result != 0 )
{
  debug_printf("Error while doing something, code %x (%s)\n", result,
                result == 7 ? "ERROR_YES" :
                result == 8 ? "ERROR_NO" :
                result == 9 ? "ERROR_FILE_NOT_FOUND" :
                "Unknown");
}
4
indiv

Comme d'autres l'ont souligné, ils sont agréables pour de courtes conditions simples. Je les aime particulièrement pour les valeurs par défaut (un peu comme l'utilisation et o en javascript et python), par exemple.

int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;

Une autre utilisation courante consiste à initialiser une référence en C++. Étant donné que les références doivent être déclarées et initialisées dans la même instruction, vous ne pouvez pas utiliser une instruction if.

SomeType& ref = pInput ? *pInput : somethingElse;
3
maccullt

Seulement quand:

$ var = (simple> test? simple_result_1: simple_result_2);

BAISER.

3
Jared Farrish

Eh bien, la syntaxe est horrible. Je trouve les ifs fonctionnels très utiles et rend souvent le code plus lisible.

Je suggérerais de créer une macro pour la rendre plus lisible, mais je suis sûr que quelqu'un peut proposer un horrible boîtier Edge (comme il en existe toujours avec CPP).

3
Marcin

J'utilise généralement dans des choses comme ça:

before:

if(isheader)
    drawtext(x,y,WHITE,string);
else
    drawtext(x,y,BLUE,string);

after:

    drawtext(x,y,isheader==true?WHITE:BLUE,string);
3
KPexEA

Pour les tâches simples comme l'attribution d'une valeur différente en fonction d'une condition, elles sont excellentes. Je ne les utiliserais pas quand il y a des expressions plus longues en fonction de la condition.

2
Svet

Si vous et vos collègues comprenez ce qu'ils font et qu'ils ne sont pas créés en groupes massifs, je pense qu'ils rendent le code moins complexe et plus facile à lire car il y a tout simplement moins de code.

La seule fois où je pense que les opérateurs ternaires rendent le code plus difficile à comprendre, c'est lorsque vous avez plus de 3 ou 4 sur une ligne. La plupart des gens ne se souviennent pas qu'ils ont une bonne priorité et lorsque vous en avez une pile, cela fait de la lecture du code un cauchemar.

2
Alex

J'ai récemment vu une variation sur les opérateurs ternaires (enfin, en quelque sorte) qui font que la variante standard "()?:" Semble être un modèle de clarté:

var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]

ou, pour donner un exemple plus tangible:

var Name = ['Jane', 'John'][Gender == 'm'];

Attention, c'est Javascript, donc des choses comme ça pourraient ne pas être possibles dans d'autres langues (heureusement).

2
pilsetnieks

Beaucoup de réponses ont dit: cela dépend. Je trouve que si la comparaison ternaire n'est pas visible dans une analyse rapide du code, elle ne doit pas être utilisée.

Comme problème secondaire, je pourrais également noter que son existence même est en fait un peu une anomalie en raison du fait qu'en C, les tests de comparaison sont une déclaration. Dans Icon, la construction if (comme la plupart de Icon) est en fait une expression. Vous pouvez donc faire des choses comme:

x[if y > 5 then 5 else y] := "Y" 

... que je trouve beaucoup plus lisible qu'un opérateur de comparaison de ternery. :-)

Il y a eu récemment une discussion sur la possibilité d'ajouter le ?: à Icon, mais plusieurs personnes ont correctement souligné qu'il n'y avait absolument aucun besoin en raison de la façon dont if fonctionne.

Ce qui signifie que si vous pouviez le faire en C (ou dans n'importe quel autre langage ayant l'opérateur de ternerie), vous n'auriez en fait pas du tout besoin de l'opérateur de ternerie.

2
staticsan

Pour les cas simples, j'aime bien l'utiliser. En fait, il est beaucoup plus facile de lire/coder par exemple comme paramètres pour des fonctions ou des choses comme ça. Aussi pour éviter la nouvelle ligne que j'aime garder avec tous mes if/else.

Nesetting ce serait un gros NON-NON dans mon livre.

Donc, en reprenant, pour un seul si/sinon j'utiliserai l'opérateur ternaire. Pour les autres cas, un if/else if/else (ou un interrupteur) normal

2
Rodrigo Gómez

J'aime le cas particulier de Groovy de l'opérateur ternaire, appelé l'opérateur Elvis:?:

expr ?: default

Ce code est évalué à expr s'il n'est pas nul et par défaut s'il l'est. Techniquement, ce n'est pas vraiment un opérateur ternaire, mais il est définitivement lié et économise beaucoup de temps/de frappe.

2
Steve Losh

Je traite les opérateurs ternaires un peu comme GOTO. Ils ont leur place, mais c'est quelque chose que vous devriez généralement éviter pour rendre le code plus facile à comprendre.

2
Dan Walker

L'opérateur ternaire, haut la main. Ils ne sont pas complexes si vous formatez correctement. Prenez l'exemple de l'année bissextile de @paxdiablo:

$isLeapYear = 
   (($year % 400) == 0)
   ? 1
   : ((($year % 100) == 0)
      ? 0
      : ((($year % 4) == 0)  
         ? 1 
         : 0));

Cela peut être écrit plus concis et être rendu beaucoup plus lisible avec ce formatage:

//--------------test expression-----result
$isLeapYear = (($year % 400) == 0) ? 1 : 
              ((($year % 100) == 0)? 0 : 
              ((($year % 4) == 0)  ? 1 : 
                                     0));//default result
1
jeremysawesome

l'utiliser pour:

  • accéder aux propriétés d'un objet (tableau):
    var status = statuses[error == null ? 'working' : 'stopped'];
    
  • déclarations de retour:
    
    function getFullName(){
        return  this.isMale() ? "Mr. " : "Ms. "+ this.name;
    }
    
  • initialiser les variables:

    
    var formMethod = DEBUG_FLAG == true ? "GET" : "POST";
    
    • valider les arguments:
    function(object){
    var prop1 =  typeof object.property == 'undefined' 
             ? "default prop" 
             : object.property;
    //...
    }

les exemples de code sont en javascript

1
gion_13

Ma règle empirique récemment formulée pour déterminer si vous devez utiliser l'opérateur ternaire est la suivante:

  • si votre code choisit entre deux valeurs différentes, allez-y et utilisez l'opérateur ternaire.
  • si votre code choisit entre deux chemins de code différents, respectez une instruction if.

Et soyez gentil avec les lecteurs de votre code. Si vous imbriquez des opérateurs ternaires, formatez le code pour rendre cette imbrication évidente.

1
Travis

Je dirais que le nombre de conditions dans une expression logique rend la lecture plus difficile. Cela est vrai d'une instruction if et cela est vrai d'un ternaire opérateur. Dans un monde parfait, il devrait y avoir ne raison résumable de prendre une branche plutôt que d'autres. Il y a de fortes chances qu'il s'agisse davantage d'une "règle commerciale" si votre explication est "uniquement lorsque ce groupe d'états se produit".

Cependant, dans le monde réel, nous n'ajoutons pas d'étapes intermédiaires pour plier les états en un seul état exprimable simplement pour obéir au cas idéal. Nous avons fait des déductions sur plusieurs États et devons prendre une décision sur la façon de les gérer.

I comme ternaires car il est possible de faire n'importe quoi avec une instruction if.

if( object.testSomeCondition()) { 
    System.exec( "format c:" );
}
else {
    a++;
}

D'autre part:

a += ( object.testSomeCondition() ? 0 : 1 );

indique clair que le but est de trouver une valeur pour a. Bien sûr, conformément à cela, il y a probablement ne devrait pas être plus que des effets secondaires raisonnables.

  • J'utilise un if pour les conditions longues ou complexes après avoir décidé si j'ai le temps de retravailler les conditions en amont afin de répondre à une question plus simple. Mais quand j'utilise un if, j'encore essaie de faire parallèle le traitement, juste sous une condition différente.

    if (  user.hasRepeatedlyPressedOKWithoutAnswer() 
       && me.gettingTowardMyLunchtime( time )
       ) {
        ...
    }
    
  • Mon objectif est également near - traitement à flux unique. Donc j'essaie souvent pas de faire un else et un if est simplement une étape hors du chemin commun. Lorsque vous effectuez beaucoup de traitement à flux unique, il est beaucoup plus difficile pour les bogues de se cacher dans votre code en attendant cette seule condition qui sautera et cassera les choses.

  • Comme je l'ai dit ci-dessus, si vous utilisez un ternaire pour définir ne chose, ou si vous avez un petit nombre de cas que vous souhaitez tester afin de le définir sur une valeur, alors je viens de comme le lisibilité d'un ternaire.

  • Avec une mise en garde -> PAS DE CLAUSES COMPLEXES vraies

    a = b == c ? ( c == d ? ( c == e ? f : g ) : h ) : i;
    

Bien sûr, cela peut être décomposé en:

a = b != c ? i
  : c != d ? h
  : c == e ? f
  :          g
  ;

Et cela ressemble à une table de vérité (compressée).

N'oubliez pas qu'il existe plus important facteurs de lisibilité, l'un d'eux est la longueur du bloc et l'autre le niveau d'indentation. Faire des choses simples dans les ternaires ne crée pas un élan vers des niveaux d'indentation de plus en plus poussés.

1
Axeman

Non, ils sont difficiles à lire. If/Else est beaucoup plus facile à lire.

C'est mon opinion. Votre kilométrage peut varier.

1
Genericrich

Je l'aime beaucoup. Quand je l'utilise, je l'écris comme un if-then-else: une ligne pour la condition, l'action vraie et l'action fausse. De cette façon, je peux les imbriquer facilement.

Exemple:

 x = (a == b 
? (sqrt (a) -2) 
: (a * a + b * b) 
); 
 
 x = (a == b 
? (sqrt (a) -2) 
: (a * a + b * b) 
) ; 
 x = (a == b 
? (c> d 
? (sqrt (a) -2) 
: (c + cos (d) ) 
) 
: (a * a + b * b) 
); 

Pour moi, c'est assez facile à lire. Cela facilite également l'ajout de sous-cas ou la modification de cas existants.

0
mjcohenw

Personne ne semble mentionner l'utilisation de l'opérateur ternaire, au moins dans des langages comme D qui prennent en charge l'inférence de type, pour permettre à l'inférence de type de fonctionner pour des types de modèles incroyablement compliqués.

auto myVariable = fun();  
// typeof(myVariable) == Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)).

// Now I want to declare a variable and assign a value depending on some
// conditional to it.
auto myOtherVariable = (someCondition) ? fun() : gun();

// If I didn't use the ternary I'd have to do:
Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)) myLastVariable;  // Ugly.
if(someCondition) {
    myLastVariable = fun();
} else {
    myLastVariable = gun():
}
0
dsimcha

Non, les opérateurs ternaires pas augmentent la complexité. Malheureusement, certains développeurs sont tellement orientés vers un style de programmation impératif qu'ils rejettent (ou n'apprendront pas) autre chose. Je ne pense pas que, par exemple:

int c = a < b ? a : b;

est "plus complexe" que l'équivalent (mais plus verbeux):

int c;
if (a < b) {
    c = a;
} else {
    c = b;
}

ou encore plus maladroit (que j'ai vu):

int c = a;
if (!a < b) {
    c = b;
}

Cela dit, examinez attentivement vos alternatives au cas par cas. En supposant un développeur correctement formé, demandez lequel exprime le plus succinctement l'intention de votre code et suivez-le.

0
joel.neely

J’étais dans le camp "les opérateurs ternaires rendent une ligne illisible", mais ces dernières années, j’ai appris à les aimer lorsqu’ils sont utilisés avec modération. Les opérateurs ternaires sur une seule ligne peuvent augmenter la lisibilité si tout le monde dans votre équipe comprend ce qui se passe. C'est une façon concise de faire quelque chose sans les frais généraux de nombreuses accolades pour le bien des accolades.

Les deux cas où je ne les aime pas: s’ils vont trop loin au-delà de la barre des 120 colonnes ou s’ils sont intégrés dans d’autres opérateurs ternaires. Si vous ne pouvez pas exprimer rapidement, facilement et de manière lisible ce que vous faites chez un opérateur ternaire. Utilisez ensuite l'équivalent if/else.

0
Joe Basirico

Ça dépend :)

Ils sont utiles lorsqu'il s'agit de références éventuellement nulles (btw: Java a vraiment besoin d'un moyen pour comparer facilement deux chaînes éventuellement nulles).

Le problème commence lorsque vous imbriquez plusieurs opérateurs ternaires dans une seule expression.

0
ajuc

Non (sauf s'ils sont mal utilisés). Lorsque l'expression fait partie d'une expression plus large, l'utilisation d'un opérateur ternaire est souvent beaucoup plus claire.

0
Denis Hennessy

L'opérateur ternaire est extrêmement utile pour produire de manière concise des listes séparées par des virgules. Voici un exemple Java:

    int[] iArr = {1,2,3};
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < iArr.length; i++) {
        sb.append(i == 0 ? iArr[i] : "," + iArr[i]);
    }
    System.out.println(sb.toString());

produit: "1,2,3"

Sinon, le boîtier spécial pour la dernière virgule devient ennuyeux.

0
Julien Chastang

Si vous essayez de réduire la quantité de lignes dans votre code ou de refactoriser le code, alors allez-y.

Si vous vous souciez du prochain programmeur qui doit prendre 0,1 milliseconde supplémentaire pour comprendre l'expression, allez-y quand même.

0
Jobo

Réduire le code ne signifie pas toujours qu'il est plus facile à analyser. En diffère d'une langue à l'autre. Dans PHP par exemple, les espaces et les sauts de ligne sont encouragés car le lexeur de PHP décompose d'abord le code en bits commençant par les sauts de ligne, puis les espaces. Donc, je ne vois pas de problème de performances, sauf si moins d'espace est utilisé.

Mauvais:

($var)?1:0;

Bien:

($var) ? 1 : 0;

Cela ne semble pas être un gros problème, mais avec le code de lexing en PHP, les espaces sont essentiels. De plus, il se lit également un peu mieux de cette façon.

0
SoSo

chaîne someSay = bCanReadThis? "Non Oui";

0
Steven A. Lowe

J'utilise et recommande des ternaires pour éviter les lignes de code dans des situations où la logique est triviale.

int i;
if( piVal ) {
    i = *piVal;
} else {
    i = *piDefVal;
}

Dans le cas ci-dessus, je choisirais un ternaire, car il a moins de bruit:

int i = ( piVal ) ? *piVal : *piDefVal;

De même, les valeurs de retour conditionnelles sont de bons candidats:

return ( piVal ) ? *piVal : *piDefVal;

Je pense que la compacité peut améliorer la lisibilité, ce qui contribue à améliorer la qualité du code.

Mais lisibilité dépend toujours de l'audience du code.

Les lecteurs doivent être capables de comprendre le a ? b : c modèle sans aucun effort mental. Si vous ne pouvez pas présumer cela, optez pour la version longue.

0
mar10

Je pense que cela dépend vraiment du contexte dans lequel ils sont utilisés.

Quelque chose comme ça serait une façon vraiment déroutante, bien qu'efficace, de les utiliser:

 __CRT_INLINE int __cdecl getchar (void)
{
   return (--stdin->_cnt >= 0)
          ?  (int) (unsigned char) *stdin->_ptr++
          : _filbuf (stdin);
}

Cependant, ceci:

c = a > b ? a : b;

est parfaitement raisonnable.

Personnellement, je pense qu'ils devraient être utilisés lorsqu'ils réduisent les déclarations FI trop verbeuses. Le problème est que les gens en sont pétrifiés ou les aiment tellement qu'ils sont utilisés presque exclusivement au lieu des déclarations des FI.

0
Onion-Knight

Comment gagnerait-on un concours de code obscurci sans l'opérateur ternaire?!

Personnellement, je l'utilise, le cas échéant, mais je ne pense pas que je l'aurais jamais imbriqué. C'est très utile, mais il a quelques inconvénients en ce sens qu'il rend le code plus difficile à lire et est utilisé dans d'autres langages dans d'autres opérations (comme le contrôle nul de Groovy).

0
billjamesdev

Je suis d'accord avec les sentiments de nombreuses affiches ici. L'opérateur ternaire est parfaitement valide tant qu'il est utilisé correctement et n'introduit pas d'ambiguïté (pour être juste, vous pouvez dire cela à propos de n'importe quel opérateur/construction).

J'utilise souvent l'opérateur ternaire dans du code intégré pour clarifier ce que fait mon code. Prenez les exemples de code suivants (simplifiés à des fins de clarté):

Extrait 1:

int direction = read_or_write(io_command);

// Send an I/O
io_command.size = (direction==WRITE) ? (32 * 1024) : (128 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);

Extrait 2:

int direction = read_or_write(io_command);

// Send an I/O
if (direction == WRITE) {
    io_command.size = (32 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
} else {
    io_command.size = (128 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
}

Ici, j'expédie une demande d'entrée ou de sortie. Le processus est le même que la demande soit en lecture ou en écriture, seule la taille d'E/S par défaut change. Dans le premier exemple, j'utilise l'opérateur ternaire pour indiquer clairement que la procédure est la même et que le champ size obtient une valeur différente selon la direction des E/S. Dans le deuxième exemple, il n'est pas aussi clair que l'algorithme pour les deux cas est le même (d'autant plus que le code croît beaucoup plus longtemps que trois lignes). Le deuxième exemple serait plus difficile à synchroniser avec le code commun. Ici, l'opérateur ternaire exprime mieux la nature largement parallèle du code.

L'opérateur ternaire a un autre avantage (bien qu'il ne soit normalement qu'un problème avec les logiciels embarqués). Certains compilateurs ne peuvent effectuer certaines optimisations que si le code n'est pas "imbriqué" au-delà d'une certaine profondeur (c'est-à-dire à l'intérieur d'une fonction, vous augmentez la profondeur d'imbrication de 1 chaque fois que vous entrez une instruction if, loop ou switch et la diminuez de 1 lorsque vous le laissez). À l'occasion, l'utilisation de l'opérateur ternaire peut minimiser la quantité de code qui doit être à l'intérieur d'un conditionnel (parfois au point où le compilateur peut optimiser le conditionnel) et peut réduire la profondeur d'imbrication de votre code. Dans certains cas, j'ai pu restructurer une logique à l'aide de l'opérateur ternaire (comme dans mon exemple ci-dessus) et réduire suffisamment la profondeur imbriquée de la fonction pour que le compilateur puisse effectuer des étapes d'optimisation supplémentaires. Certes, c'est un cas d'utilisation assez étroit, mais je pensais que cela valait la peine d'être mentionné de toute façon.

0
bta

À petites doses, ils peuvent réduire le nombre de lignes et rendre le code plus lisible; en particulier si le résultat est quelque chose comme définir une chaîne de caractères sur "Oui" ou "Non" en fonction du résultat d'un calcul.

Exemple:

char* c = NULL;
if(x) {
  c = "true";
}else {
  c = "false";
}

comparé à:

char* c = x ? "Yes" : "No";

Le seul bogue qui peut se produire dans des tests simples comme celui-ci est l'attribution d'une valeur incorrecte, mais comme le conditionnel est généralement simple, il est moins probable que le programmeur se trompe. Le fait que votre programme imprime la mauvaise sortie n'est pas la fin du monde et devrait être pris en compte dans toutes les phases de révision de code, de test en laboratoire et de test de production.

Je vais contrer mon propre argument car il est désormais plus difficile d'utiliser des mesures de couverture de code pour vous aider à savoir à quel point vos cas de test sont bons. Dans le premier exemple, vous pouvez tester la couverture sur les deux lignes d'affectation; si l'un n'est pas couvert, vos tests n'exercent pas tous les flux de code possibles.

Dans le deuxième exemple, la ligne s'affiche comme étant exécutée quelle que soit la valeur de X, vous ne pouvez donc pas être certain d'avoir testé le chemin alternatif (YMMV selon la capacité de vos outils de couverture).

Cela est d'autant plus important avec la complexité croissante des tests.

0
Adam Hawes

si votre opérateur ternaire finit par prendre toute la largeur de l'écran, je ne l'utiliserais pas. Je le garde juste pour vérifier une condition simple et retourner des valeurs simples:

int x = something == somethingElse ? 0 : -1;

Nous avons en fait un code désagréable comme celui-ci en production ... pas bon:

int x = something == (someValue == someOtherVal ? string.Empty : "Blah blah") ? (a == b ? 1 : 2 ): (c == d ? 3 : 4);
0
Ricardo Villamil

J'aime l'opérateur dans certaines situations, mais je pense que certaines personnes ont tendance à trop l'utiliser et que cela peut rendre le code plus difficile à lire.

J'ai récemment trébuché sur cette ligne dans un code open source que je travaille à modifier.

where 
               (active == null ? true : 
               ((bool)active ? p.active : !p.active)) &&... 

Au lieu de

where ( active == null || p.active == active) &&...

Je me demande si l'utilisation ternaire ajoute une surcharge supplémentaire à l'instruction LINQ dans ce cas.

0
Tim

Anecdote intéressante: j'ai vu l'optimiseur peser l'opérateur ternaire comme moins "lourd" aux fins de l'inline que l'équivalent si. J'ai remarqué cela avec les compilateurs Microsoft, mais cela pourrait être plus répandu.

En particulier, des fonctions comme celle-ci impliqueraient:

int getSomething()
{
   return m_t ? m_t->v : 0;
}

Mais cela ne serait pas:

int getSomething() 
{
    if( m_t )
        return m_t->v;
    return 0;
}
0
Don Neufeld