2008-09-30 8 views

Respuesta

80

Es más útil para bucles que declaraciones if.

while(var = GetNext()) 
{ 
    ...do something with var 
} 

que de otro modo tienen que ser escritos

var = GetNext(); 
while(var) 
{ 
...do something 
var = GetNext(); 
} 
+8

Estoy de acuerdo, pero escribiría: while ((var = GetNext())! = 0) {...} sin pensarlo dos veces, en parte porque GCC se queja si no lo hago con mis opciones de compilación predeterminadas . –

+1

cierto. Suponiendo que está utilizando un lenguaje que admita declaraciones for-loop, y que aún no esté utilizando var fuera del ciclo. – Gerald

+0

en algunos idiomas, como ANSI C, las reglas de alcance no permiten este enfoque, @KerrekSB – wirrbel

22

Puede ser útil si usted está llamando a una función que devuelve o datos para trabajar o una bandera para indicar un error (o que ya terminaste).

Algo así como:

while ((c = getchar()) != EOF) { 
    // process the character 
} 

// end of file reached... 

lo personal es un idioma que no soy aficionado a la enorme, pero a veces la alternativa es más feo.

28

Es más útil si se llama a una función:

if (n = foo()) 
{ 
    /* foo returned a non-zero value, do something with the return value */ 
} else { 
    /* foo returned zero, do something else */ 
} 

Claro, usted puede simplemente poner el n = foo(); en una declaración separada, entonces si (n), pero creo que lo anterior es una expresión bastante legible.

+0

creo que debe encerrarlo entre paréntesis o gcc se quejará con: advertencia: se sugieren paréntesis alrededor de asignación utilizados como valor de verdad [-Wparentheses] De esta manera: si ((n = foo())) { // hacer algo con el valor de retorno } else { // foo devuelto cero/NULL, hacer otra cosa } –

8

La expresión idiomática es más útil cuando escribe un bucle while en lugar de una instrucción if. Para una declaración if, puede dividirla según lo describe. Pero sin esta construcción, ya sea que usted tiene que repetir:

c = getchar(); 
while (c != EOF) { 
    // ... 
    c = getchar(); 
} 

o utilizar una estructura de bucle-and-a-media:

while (true) { 
    c = getchar(); 
    if (c == EOF) break; 
    // ... 
} 

Por lo general se prefiere el bucle-y-a- mitad de forma.

8

GCC puede ayudar a detectar (con -Wall) si involuntariamente intenta utilizar una asignación como un valor de verdad, en caso de que recomienda que escribe

if ((n = foo())) { 
    ... 
} 

es decir, use paréntesis adicionales para indicar que esto es realmente lo que quiere.

3

En PHP, por ejemplo, es útil para el bucle a través de resultados de base de datos SQL:

while ($row = mysql_fetch_assoc($result)) { 
    // Display row 
} 

Esto se ve mucho mejor que:

$row = mysql_fetch_assoc($result); 
while ($row) { 
    // Display row 
    $row = mysql_fetch_assoc($result); 
} 
+3

Esto también tiene el claro efecto secundario de $ row que no se extiende más allá de ese ciclo y, por lo tanto, es elegible para la recolección de basura antes (en los idiomas que sí lo hacen) GC de todos modos). –

23

Lo encuentro más útil en cadenas de acciones que a menudo implican la detección de errores, etc.

if ((rc = first_check(arg1, arg2)) != 0) 
{ 
    report error based on rc 
} 
else if ((rc = second_check(arg2, arg3)) != 0) 
{ 
    report error based on new rc 
} 
else if ((rc = third_check(arg3, arg4)) != 0) 
{ 
    report error based on new rc 
} 
else 
{ 
    do what you really wanted to do 
} 

La alternativa (no utilizando la asignación en la condición) es:

rc = first_check(arg1, arg2); 
if (rc != 0) 
{ 
    report error based on rc 
} 
else 
{ 
    rc = second_check(arg2, arg3); 
    if (rc != 0) 
    { 
     report error based on new rc 
    } 
    else 
    { 
     rc = third_check(arg3, arg4); 
     if (rc != 0) 
     { 
      report error based on new rc 
     } 
     else 
     { 
      do what you really wanted to do 
     } 
    } 
} 

Con la comprobación de errores prolongada, la alternativa puede funcionar con el RHS de la página mientras que la versión asignación-in-condicional no hace eso.

+0

Sí, lo hice para evitar el exceso de anidación y luego busqué en línea para ver si era una práctica común. Al final, decidí no hacerlo porque en realidad solo tenía un caso más, pero esta parece ser una razón legítima para poner la tarea en la condición. – Ibrahim

+0

¡Los compañeros de trabajo lo odian! Para mí, al menos en la mayoría de los casos, es mucho más fácil de mantener que un árbol gigante o muchos beneficios. Prefiero el retorno individual de una función ... – Nathan

3

La respuesta corta es que Expression-oriented lenguajes de programación permiten un código más sucinto. No te fuerces a separate commands from queries.

+0

Es una lucha constante para imponer la codificación sin asignaciones en if(), while() y otras declaraciones similares. C/C++ son notorios por los efectos secundarios de los que a menudo resultan ser errores, especialmente cuando agregamos los operadores ++ y -. –

2

La otra ventaja viene durante el uso de gdb. En el siguiente código, el código de error no se conoce si tuviéramos un solo paso.

while (checkstatus() != -1) { 
    // process 
} 

En lugar

while (true) { 
    int error = checkstatus(); 
    if (error != -1) 
     // process 
    else 
     //fail 
} 

Ahora, durante un solo paso que se puede saber cuál era el código de error de retorno de la checkStatus().

-2

La razón es:

  1. Mejora del rendimiento (A veces)

  2. Menor de código (siempre)

Tomemos un ejemplo: Hay un método someMethod() y en un if condición en la que desea verificar si el valor de retorno del método es null. Si no, vas a usar el valor de retorno nuevamente.

If(null != someMethod()){ 
    String s = someMethod(); 
    ...... 
    //Use s 
} 

Se obstaculizará el rendimiento ya que está llamando al mismo método dos veces. En lugar de usar:

String s; 
If(null != (s = someMethod())) { 
    ...... 
    //Use s 
} 
Cuestiones relacionadas