2011-07-16 16 views
27

duplicados posibles:
Why does this go into an infinite loop?i = i ++ no incrementa i. ¿Por qué?

Cosas como i = i++ tienen un comportamiento no definido en C y C++ porque el valor de un objeto de escalar es cambios dos veces dentro de la misma expresión sin intervenir punto secuencia.

Sin embargo supongo que este tipo de expresiones tiene un comportamiento bien definido en C# o Java, porque que yo sepa la evaluación del argumento va a la izquierda a la derecha y hay secuencia de puntos por todas partes.

Dicho esto, esperaría que i = i++ fuera equivalente a i++. Pero no lo es. El siguiente programa produce 0.

using System; 
class Program 
{ 
    static void Main(string[] args) 
    { 
     int i = 0; 
     i = i++; 
     Console.WriteLine(i); 
    } 
} 

¿Podría ayudarme a entender por qué?

responsabilidad: Soy plenamente consciente de que si el comportamiento de las construcciones anteriormente mencionado se define, son tonto, inútil, ilegibles, innecesario y no se deben utilizar en el código. Tengo curiosidad.

+6

@Downvoter: ¿Te gustaría dejar un comentario? –

+1

Por lo general, no :) – Tigran

+5

Esto se preguntó el año pasado sobre Java, pero respondió en C# (ambos funcionan de manera similar para este caso): http://stackoverflow.com/questions/3831341/why-does-this-go- into-an-infinite-loop – BoltClock

Respuesta

38

El comportamiento está bien definido en C# y el orden de evaluación es:

  1. lado izquierdo i se evalúa en el lado derecho variable de i
  2. se evalúa a 0, y i se incrementa (ahora i==1)
  3. La asignación se ejecuta, se establece i a 0. (ahora i==0)

El resultado final es i==0.

En general, primero crea un árbol de expresiones. Para evaluarlo, primero evalúa el lado izquierdo, luego el derecho y finalmente la operación en la raíz. Haz eso recursivamente.

+0

¡Ah! Que tiene sentido. Soy tonto :) –

+3

En Java, en ocasiones puedes observar el valor '1' de una cadena paralela si haces' i' volátil (en mi prueba típicamente 65 veces en 100 millones de iteraciones). – starblue

+1

i = ++ también debería funcionar bien. – arkoak

17

El resultado de la expresión de incremento posterior i++ es el valor original de i. Así que después de i++ se ha evaluado (incrementando i), se asigna el valor antiguo de i a ... i.

sólo tiene que utilizar

i++; 

;)

+1

Estaba al tanto de la diferencia de preincremento y postincremento. Estaba confundido porque esperaba que el efecto secundario del incremento tuviera lugar después de la evaluación de toda la expresión ... Obviamente estaba equivocado –

+0

@Armen, sí, C# es casi de izquierda a derecha –

+3

@Marc Me parece que la formulación que una expresión se evalúa de izquierda a derecha confusa. Prefiero pensar en la expresión como un árbol que luego se evalúa recursivamente. Y cada nodo evalúa primero sus argumentos de izquierda a derecha y finalmente se ejecuta solo. – CodesInChaos

3

Bueno, la expresión lado derecho deben ser evaluados antes de la asignación puede tener lugar. Ahora, i++ evaluará al valor actual de i, y el valor de i posteriormente se incrementará en uno. Sin embargo, la asignación aún no se ha realizado y, cuando lo esté, sobrescribirá el valor actual de i (1) con la expresión evaluada de rhs, que en su caso fue 0.

La diferencia clave es entre ++i (pre-incremento, que evalúa al valor nuevo de idespués de incrementación) y i++, o post-incremento, que se evalúa como el valor actual de iantes de incremento.

¿Había utilizado ++i lugar, la expresión lado derecho habría evaluado a 1, lo que resulta en i == 1.

15

i = ++i es el código que hace lo que piensa que está pasando aquí. i++ en realidad se comporta de una manera un poco diferente.

Con i++, el valor de i aumenta, pero el valor de i++ no es el nuevo valor de i, que es el valor anterior.Entonces cuando haces i = i++, estás diciendo "aumenta el valor de i, luego configura i al valor anterior".

+5

en la primera línea; simplemente 'i ++;' sería el "código que está buscando" –

+3

No creo que esté buscando ningún código, pero está buscando una mejor comprensión del lenguaje C#. En particular, en qué orden ocurren los efectos secundarios y cómo se comporta el resultado de múltiples asignaciones a la misma variable dentro de una expresión. – CodesInChaos

+1

@Marc: Excepto que no estoy buscando ningún código :) –

Cuestiones relacionadas