EDIT : Ok, je l'ai.
La première chose à dire est qu'il est évident que vous ne devriez pas utiliser ce code de toute façon. Cependant, lorsque vous le développez, il devient équivalent à :
j = j ^ (i = i ^ (j = j ^ i));
(Si nous utilisions une expression plus compliquée telle que foo.bar++ ^= i
il serait important que l ++
n'a été évalué qu'une seule fois, mais ici je crois que c'est plus simple).
Maintenant, l'ordre d'évaluation des opérandes est toujours de gauche à droite, donc pour commencer nous obtenons :
j = 36 ^ (i = i ^ (j = j ^ i));
Cette étape (ci-dessus) est la plus importante. Nous nous sommes retrouvés avec 36 comme LHS pour l'opération XOR qui est exécutée en dernier. La LHS n'est pas "la valeur de j
après l'évaluation de l'ERS".
L'évaluation du RHS de ^ implique l'expression "un niveau emboîté", elle devient donc :
j = 36 ^ (i = 25 ^ (j = j ^ i));
Ensuite, en regardant le niveau le plus profond de l'imbrication, nous pouvons substituer à la fois i
et j
:
j = 36 ^ (i = 25 ^ (j = 25 ^ 36));
... qui devient
j = 36 ^ (i = 25 ^ (j = 61));
L'affectation à j
dans le RHS se produit en premier, mais le résultat est de toute façon écrasé à la fin, donc nous pouvons l'ignorer - il n'y a pas d'autres évaluations de j
avant l'affectation finale :
j = 36 ^ (i = 25 ^ 61);
C'est maintenant équivalent à :
i = 25 ^ 61;
j = 36 ^ (i = 25 ^ 61);
Ou :
i = 36;
j = 36 ^ 36;
Ce qui devient :
i = 36;
j = 0;
I pensez à c'est correct, et cela mène à la bonne réponse... mes excuses à Eric Lippert si certains détails concernant l'ordre d'évaluation sont légèrement erronés :(
2 votes
Ce serait la même réponse que celle donnée pour : stackoverflow.com/questions/3741440 ou beaucoup d'autres dans la colonne connexe. Même s'ils disent C++ et qu'il s'agit de C#, les mêmes règles s'appliquent.
8 votes
@Daemin : Non, les mêmes règles Ne le fais pas. appliquer. C'est un comportement indéfini en C++, mais je ne crois pas qu'il soit indéfini en C#.
3 votes
@Daemin - Voici un billet connexe d'Eric Lippert, il y a tout juste deux jours : stackoverflow.com/questions/5538193/ en particulier : "Les autres réponses soulignent que dans les langages de programmation C et C++, les spécifications du langage ne précisent pas dans quel ordre les effets secondaires semblent se produire si l'effet secondaire et son observation se trouvent dans le même "point de séquence", comme c'est le cas ici. [...] Le C# ne permet pas ce genre de lattitude. En C#, un effet secondaire à gauche est observé comme s'étant produit au moment où le code à droite s'exécute."
0 votes
@JonSkeet & @Kobi Point pris, j'ai supposé que le même genre d'ordre indéfini d'effet secondaire dans un point de séquence serait présent en C# comme en C & C++. Je suppose donc que l'expression devrait fonctionner si elle est mise entre crochets de manière appropriée. Inutile de dire que l'utilisation de l'astuce XOR swap n'est pas une chose sage à faire dans les temps modernes.
0 votes
Vous avez déjà entendu parler de la précédence des opérateurs et de l'associativité ?
2 votes
Un jour, j'aimerais penser à une question suffisamment intéressante pour que Jon Skeet la tweete...
8 votes
Pour ceux qui ont fermé la question - l'autre question traite du C, C++ où le résultat est indéfini à cause d'un manque de points de séquence. Alors que cette question porte sur le C#, où la réponse est bien définie, mais différente de ce que l'on pourrait attendre. Je ne traiterais donc pas cette question comme un doublon, car les réponses sont nettement différentes.
1 votes
Quoi ? Le C# n'a pas la construction (j,k) = (k,j) ? OMG !