2010-07-22 24 views
93

¿Cuáles son los beneficios y desventajas del operador?: En comparación con la instrucción if-else estándar. Las más obvias son:Ventajas del uso del operador condicional?: (Ternario)

condicional: Operador

  • más corto y conciso cuando se trata de comparaciones de valores directos y asignaciones
  • no parece ser tan flexible como el/else if construir

estándar If/Else

  • se puede aplicar a más situaciones (como las llamadas de función)
  • A menudo son innecesariamente largo

legibilidad parece variar para cada uno en función de la declaración. Por un tiempo después de haber estado expuesto por primera vez al operador?: Me tomó algo de tiempo digerir exactamente cómo funcionó. ¿Recomendaría usarlo siempre que sea posible, o apegarse a if/else dado que trabajo con muchos no programadores?

+8

Usted ya lo hice la esencia de eso. –

+0

Solo he hecho un poco en C#, pero la mayoría de los lenguajes permiten llamadas a funciones dentro del operador condicional.C realmente no? Eso parece muy extraño ... –

+1

@Nicholas Knight: Supongo que el OP significa que no se puede hacer, por ejemplo, 'SomeCheck()? DoFirstThing(): DoSecondThing(); '- debe usar la expresión para devolver un valor. –

Respuesta

111

Básicamente, recomendaría usarlo solo cuando el enunciado resultante es extremadamente corto y representa un aumento significativo en la concisión sobre el equivalente if/else sin sacrificar la legibilidad.

buen ejemplo:

int result = Check() ? 1 : 0; 

Mal ejemplo:

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

Buena llamada, pero para el registro, eso es "concisión". – mquander

+5

@mquander, ¿estás seguro de eso? http://www.merriam-webster.com/dictionary/concise –

+1

Hmm, ve la figura; quizás también puede ser cualquiera de los dos. – mquander

10

Encuentro particularmente útil cuando realizo el desarrollo web si quiero establecer una variable en un valor enviado en la solicitud si está definido o en algún valor predeterminado si no lo está.

+3

+1 valores predeterminados en web dev es un ejemplo excelente un buen lugar para usar el operador ternario –

+1

el operador coalescente nulo ('??') sería más adecuado en ese caso ... –

3

Si Soy la creación de un valor y sé que siempre será una línea de código para hacerlo, que suelen utilizar el operador ternario (condicional). Si existe la posibilidad de que mi código y lógica cambien en el futuro, uso un if/else ya que es más claro para otros programadores.

De más interés para usted puede ser el ?? operator.

3

La ventaja del operador condicional es que es un operador. En otras palabras, devuelve un valor. Como if es una declaración, no puede devolver un valor.

4

Una cosa para reconocer al usar el operador ternario es que es una expresión, no una declaración.

En los lenguajes funcionales como esquema de la distinción no existe:

(si (> ab) ab)

condicional: Operador "no parece ser tan flexible como el if/de lo contrario construir "

En idiomas funcionales es.

Cuando programo en lenguajes imperativos, aplico el operador ternario en situaciones donde típicamente usaría expresiones (asignación, declaraciones condicionales, etc.).

3

Recomendaría limitar el uso del operador ternario (? :) a la simple asignación de línea simple si/else lógica. Algo parecido a este patrón:

if(<boolCondition>) { 
    <variable> = <value>; 
} 
else { 
    <variable> = <anotherValue>; 
} 

se podría convertir fácilmente a:

<variable> = <boolCondition> ? <value> : <anotherValue>; 

Me gustaría evitar el uso del operador ternario en situaciones que requieren if/else if/else, anidados if/else, o si/else branch logic que da como resultado la evaluación de múltiples líneas. Aplicar el operador ternario en estas situaciones probablemente resulte en un código ilegible, confuso e inmanejable. Espero que esto ayude.

5

El operador condicional es ideal para condiciones cortos, como este:

varA = boolB ? valC : valD; 

lo uso de vez en cuando, ya que toma menos tiempo para escribir algo así ... por desgracia, esta ramificación puede a veces se puede perder por otro desarrollador que navega por su código. Además, el código por lo general no es tan corto, así que generalmente ayudo a la legibilidad colocando el? y: en líneas separadas, como este:

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

Sin embargo, la gran ventaja de usar si/bloques demás (y eso que los prefiero) es que es más fácil de conseguir en la tarde y añadir un poco de lógica adicional para la rama ,

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

o añadir otra condición:

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

Así que, al final, se trata de conveniencia para usted ahora (más corto a utilizar:?) frente a la conveniencia para usted (y otros) más tarde. Es una decisión acertada ... pero, al igual que todos los demás problemas de formato de código, la única regla real es ser coherente y ser cortés con las personas que tienen que mantener (¡o calificar!) Su código.

(todo el código ojo-compilado)

1

Hay una cierta mejora en el rendimiento de la utilización de la del? operador en, por ej. MS Visual C++, pero esto es realmente algo específico del compilador. El compilador en realidad puede optimizar la rama condicional en algunos casos.

1

El escenario que más me encuentro a mí mismo de usarlo es por incumplir los valores y sobre todo en los retornos

return someIndex < maxIndex ? someIndex : maxIndex; 

Esos son realmente los únicos lugares que les resulta agradable, pero para ellos lo hacen.

Aunque si lo que buscas es un valor lógico esto puede a veces parecer una cosa apropiada a hacer:

bool hey = whatever < whatever_else ? true : false; 

Porque es muy fácil de leer y entender, pero la idea siempre debe ser lanzado para los más obvia:

bool hey = (whatever < whatever_else); 
1

Si necesita múltiples ramas en las mismas condiciones, usar un if:

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

Si necesita múltiples ramas con diferentes condiciones, entonces si el recuento de declaración sería una bola de nieve, tendrá que utilizar el ternario:

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

Además, se puede utilizar el operador ternario en la inicialización.

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

Hacer eso con si es muy desordenado:

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

No se puede poner la inicialización dentro de la/else if, ya que cambia el alcance. Pero las referencias y las variables const solo pueden vincularse en la inicialización.

10

Por lo general, elijo un operador ternario cuando tengo un código duplicado de lo contrario.

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

Con un operador ternario, esto se puede lograr con lo siguiente.

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

personalmente haría 'aVal = a> 0? a: -a; answer = calcular (aVal, b, c, d, e); 'Especialmente si' b', 'c',' d' y 'e' requieren tratamiento también. – corsiKa

+10

¿Por qué usar un condicional en este ejemplo? Simplemente obtenga Abs (a) y llame a compute() una vez. – Ash

+2

Sí, no creé el mejor ejemplo. :) –

1

El operador ternario se puede incluir dentro de un valor r, mientras que un if-then-else no puede; por otro lado, un if-then-else puede ejecutar bucles y otras instrucciones, mientras que el operador ternario solo puede ejecutar valores (posiblemente anulados).

En una nota relacionada, & & y || los operadores permiten algunos patrones de ejecución que son más difíciles de implementar con if-then-else. Por ejemplo, si uno tiene varias funciones para llamar y desea ejecutar un fragmento de código si alguno de ellos falla, puede hacerlo bien utilizando el operador & &. Hacerlo sin ese operador requerirá código redundante, un goto o una variable de bandera adicional.

46

Esto es más o menos cubiertos por las otras respuestas, pero "es una expresión" en realidad no se explica por qué es tan útil ...

En lenguajes como C++ y C#, se puede definir constantes locales (dentro de un cuerpo de método) usándolos. No

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

es lo mismo que:: Esto no es posible con una convencional si/entonces declaración porque el valor de toda una constante tiene que ser asignado dentro de esa sola declaración

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

En un similares forma en que puede insertar una expresión terciaria en otro código.A la vez que el código fuente más compacto (y en algunos casos más legibles como resultado) también puede hacer que el código máquina generado más compacto y eficiente:

MoveCar((shiftKeyDown) ? 10 : 1); 

... puede generar menos código que tener que llamar al mismo método en dos ocasiones:

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

por supuesto, también es una forma más conveniente y conciso (menos escribir, menos repetición, y puede reducir la posibilidad de errores si tiene que duplicar los trozos de código en un if/más). En los casos limpias "patrón común" como este:

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

... es simplemente más rápido para leer/análisis sintáctico/entender (una vez que está acostumbrado a ello) que la de largo aliento if/else equivalente, por lo te puede ayudar a 'grok' codificar más rápido.

Por supuesto, sólo porque es útil no quiere decir que es lo mejor que puede uso en todos los casos. Aconsejo usarlo solo para fragmentos cortos de código donde el significado es claro (o se hace más claro) usando ?: - si lo usa en código más complejo, o anida los operadores ternarios entre sí, puede hacer que el código sea terriblemente difícil de usar. leer.

+0

@JaminGrey _ "eso no significa que, cuando se crea la constante, se establece en 10 o 1". _ ¿Quiere decir _¿se refiere a eso? Los comentarios incorrectos pueden causar más confusión a los nuevos programadores de C++ que el problema que intentaba aclarar;) – Clonkex

+0

@Clonkex Correcto, gracias. =) Permítanme intentarlo de nuevo: –

+5

Para futuros lectores que se den cuenta de esto, por "* const int speed = (shiftKeyDown)? 10: 1; *", eso significa que cuando la constante * se crea primero *, se establece en 10 o 1. ** no ** significa que cada vez que se accede a la constante realiza una comprobación. (Solo en caso de que se confundiera un programador de C++ más reciente) –

10

Un uso realmente interesante es:

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

Tenga cuidado con esto en PHP, el operador ternario asocia el camino equivocado en PHP. Esencialmente, si 'foo' es falso, entonces todo se evaluará a 4 sin hacer las otras pruebas. –

+4

@TomBusby - Wow. Otra razón para odiar PHP, si eres alguien que ya odia PHP. –

4

Si bien las respuestas anteriores son válidas, y estoy de acuerdo con la legibilidad de ser importante, hay 2 puntos adicionales a considerar:

  1. en C# 6 , puedes tener métodos con cuerpo de expresión

Esto lo hace particularmente concisa para utilizar el ternario:

string GetDrink(DayOfWeek day) 
    => day == DayOfWeek.Friday 
     ? "Beer" : "Tea"; 
  1. comportamiento difiere cuando se trata de la conversión de tipo implícito.

Si tiene tipos T1 y T2 que puede tanto pueden convertir implícitamente a T, a continuación, el siguiente lo hace no trabajo:

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

(porque el compilador intenta determinar el tipo de la ternario expresión, y no hay conversión entre T1 y T2.)

Por otro lado, la versión if/else debajo d oes trabajo:

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

porque T1 se convierte en T y así es T2

3

A veces puede hacer que la asignación de un valor bool más fácil de leer a primera vista:

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

// Without 
button.IsEnabled = !someControl.HasError; 
Cuestiones relacionadas