2010-02-19 9 views
33
int x = 10; 
x += x--; 

En C# /. Net, ¿por qué es igual a lo que equivale? (estoy dejando deliberadamente la respuesta a cabo de modo que se puede adivinar y ver si tienes razón)int x = 10; x + = x--; en .Net - ¿Por qué?

+16

se comporta de esa manera debido a que nunca debe hacer nada de eso, y como tal, el comportamiento es irrelevante. –

+0

¡Pregunta interesante! – Kevin

+0

no debería adivinarme a mí mismo. parecía obvio hasta que lo pensé un segundo. mi razonamiento para pensar 20 fue que la disminución no ocurrió hasta después de la referencia y luego comencé a pensar que la referencia original se reduciría cuando la operación se compeliera, pero es un tipo de valor, pero así que supongo 19. me tonto. –

Respuesta

53

mirada a esta declaración:

x += x--; 

Esto es equivalente a:

x = x + x--; 

lo que equivale a:

int a1 = x; // a1 = 10, x = 10 
int a2 = x--; // a2 = 10, x = 9 
x = a1 + a2; // x = 20 

Así x es 20 después, y eso está garantizado por la especificación.

Lo que es también prácticamente garantizado, aunque no según las especificaciones, es que cualquiera que use dicho código será atacado por sus colegas. Sí, es bueno que el resultado sea predecible. No, no es bueno usar ese tipo de código.

+9

No es justo ... A Skeet no se le debe permitir responder estas preguntas. : P – CAbbott

+1

jaja, no se debe permitir skeet !!! ¡Codicioso! jaja. – Eric

+3

@CAbbott: desafortunadamente nadie más parece entender la diferencia entre x-- y --x! –

10

Desde el specs 7.13.2

Si el tipo de retorno del operador seleccionado es convertir implícitamente el tipo de x, la operación se evalúa como x = x op y, excepto que x se evalúa sólo una vez.

Así que su declaración es equivalente a x = x + x--; que se evalúa con el fin de izquierda a derecha y da la respuesta 20.

Tenga en cuenta que también hay una diferencia entre --x y x-- aquí. Si hubiera escrito x += --x;, esto equivaldría a x = x + --x; entonces obtendrías 19. Esto se debe a que el valor de x se decrementa y el valor resultante se usa en la expresión (a diferencia de x-- donde se usa el valor original de x en la expresión).

Esta expresión x = x + --x + x dará 28 porque el tercera vez cuarto tiempo (ver comentarios) x se evalúa es 9.

+0

¿Quizás quiso decir 20? 10 sería realmente sorprendente ...;) – Francesco

+0

@Francesco: Typo, corregido. Ahora agregué un párrafo más y * que * 10 en realidad está destinado a ser un 10. –

+0

+1 para citar la especificación. –

14

20; el "-" no ocurre hasta después de que todo se evalúa, y ese valor es sobrescrito por el lado izquierdo de los iguales.

+11

Tu nombre no es Jon Skeet, pero de todos modos votaré de nuevo. –

+4

Aunque tiene la respuesta correcta, la lógica que lo llevó allí es incorrecta. El "no ocurre hasta después de que todo se evalúa" es engañoso. En particular, la disminución ocurre antes de la asignación de 9 a x, que ocurre antes de la suma de 10 y 10, que ocurre antes de la asignación de 20 a x. El cálculo de la disminución ocurre antes de una suma y dos asignaciones, por lo que no puede ser correcto decir que no ocurre hasta que * todo * se evalúe. –

0

La respuesta es 20. Y Tom, realmente no estás tan sorprendido como parece implicar tus preguntas, ¿verdad? Y para aquellos de ustedes que asumen que la respuesta es 19, creo que están confundidos con x + = --x;

+2

Probablemente, lo que les confunde no sea --x, sino más bien, si el efecto secundario de "decremento x" ocurre antes o después del cálculo del lado izquierdo del operador + =. En el lenguaje donde x + = x-- se evalúa de derecha a izquierda, primero se calcula x--, que es 10, y se asigna 9 a x. Luego calcula el lado izquierdo, que ahora es 9. Y ahora agrega 9 a 10 y asigne eso a x, entonces, 19. C# garantiza que las expresiones se evalúan de izquierda a derecha. C++ no lo hace; un compilador de C++ puede evaluar esto de derecha a izquierda si lo desea, y tanto 19 como 20 son resultados legales. –

+0

Eric. Creo que tienes razón No podría estar mas de acuerdo. – Eric

15

Jon tiene razón.

Una buena manera de pensar acerca de esto es que hay que recordar:

1) subexpresiones siempre se evalúan de izquierda a derecha . Período. La evaluación de una subexpresión puede inducir un efecto secundario.

2) la ejecución de operadores siempre se realiza en el orden indicado entre paréntesis, precedencia y asociatividad. La ejecución de operadores puede inducir un efecto secundario.

La "x" a la izquierda de + = es la subexpresión más a la izquierda, y por lo tanto se aplica la regla (1). Su valor se calcula primero - 10.

El x-- a la derecha de + = es el siguiente en orden de izquierda a derecha, por lo que se evalúa a continuación. El valor de x-- es 10, y el efecto secundario es que x se convierte en 9. Esto es como debería ser, porque - tiene una precedencia mayor que + =, por lo que su efecto secundario se ejecuta primero.

Finalmente, el efecto secundario de + = se ejecuta en último lugar. Los dos operandos fueron 10 y 10, por lo que el resultado es asignar 20 a x.

Tengo preguntas sobre esto todo el tiempo. Recuerde, las reglas son muy sencillas: subexpresiones de izquierda a derecha, operadores en orden de precedencia, punto.

En particular, tenga en cuenta que el razonamiento comúnmente establecido "el operador es postfijo y, por lo tanto, se ejecuta después de todo lo demás" es un razonamiento incorrecto. Discuto por qué eso es incorrecto en los artículos a continuación.

Éstos son algunos de los artículos que he escrito en este tema:

http://blogs.msdn.com/ericlippert/archive/tags/precedence/default.aspx

+0

¿La adición es un punto de secuencia en C#? Está permitiendo que las personas escriban código sin entender los puntos de secuencia. Sin duda, el fin del mundo está cerca. –

Cuestiones relacionadas