Подтвердить что ты не робот

С# Pre- & Post Increment confusions

Я немного запутался в том, как компилятор С# обрабатывает до и после приращений и декрементов.

Когда я закодирую следующее:

int x = 4;
x = x++ + ++x;

x будет иметь значение 10 после этого. Я думаю, это связано с тем, что pre-increment устанавливает x в 5, что делает его 5+5 равным 10. Затем пост-инкремент будет обновлять x до 6, но это значение не будет использоваться, потому что тогда 10 будет присвоено x.

Но когда я код:

int x = 4;
x = x-- - --x;

тогда x будет 2. Может ли кто-нибудь объяснить, почему это так?

4b9b3361

Ответ 1

x-- будет 4, но будет 3 в момент --x, поэтому он будет заканчиваться на 2, тогда у вас будет

x = 4 - 2

btw, ваш первый случай будет x = 4 + 6

Вот небольшой пример, который будет печатать значения для каждой части, возможно, таким образом вы поймете это лучше:

static void Main(string[] args)
{
    int x = 4;
    Console.WriteLine("x++: {0}", x++); //after this statement x = 5
    Console.WriteLine("++x: {0}", ++x); 

    int y = 4;
    Console.WriteLine("y--: {0}", y--); //after this statement y = 3
    Console.WriteLine("--y: {0}", --y);

    Console.ReadKey();
}

выводится

x++: 4
++x: 6
y--: 4
--y: 2

Ответ 2

Давайте посмотрим на IL, который генерируется из этого утверждения

IL_0002:  ldloc.0     

Загружает значение x в стек. Stack = > (4)

IL_0003:  dup         

Дублирует самый верхний элемент в стеке. Stack = > (4, 4)

IL_0004:  ldc.i4.1    

Нажмите 1 на стек. Stack = > (1, 4, 4)

IL_0005:  sub         

Вычтите два верхних значения и нажмите результат на стек. Stack = > (3, 4)

IL_0006:  stloc.0     

Храните верхнее значение стека обратно в x. Stack = > (4)

IL_0007:  ldloc.0     

Загрузите значение x обратно в стек. Stack = > (3, 4)

IL_0008:  ldc.i4.1    

Загрузите значение 1 в стек. Stack = > (1, 3, 4)

IL_0009:  sub         

Вычтите два. Stack = > (2, 4)

IL_000A:  dup         

Дублируйте верхнее value = > (2, 2, 4)

IL_000B:  stloc.0     

Сохраните верхнее значение обратно на x. Stack = > (2, 4)

IL_000C:  sub      

Вычтите два верхних значения. Stack = > (2)

IL_000D:  stloc.0  

Сохраните это значение обратно в x. x == 2

Ответ 3

Из вашего комментария:

Я подумал, что после/до оценки полной кодовой строки выполняются пост-и предварительные приращения, но они выполняются после/перед оценкой каждого элемента в выражении.

Ваше недоразумение является чрезвычайно распространенным. Обратите внимание, что на некоторых языках, таких как C, он не указывается, когда побочный эффект становится видимым, и поэтому он является законным, но не обязательным, чтобы ваше утверждение было истинным в C.

Это не относится к С#; в С# побочные эффекты кода в левой части выражения всегда наблюдаются до того, как код с правой стороны выполняет (из одного потока, в многопоточных сценариях все ставки отключены.)

Для более подробного объяснения того, что делают операторы приращения в С#, см. ниже:

В чем разница между я ++ и ++ i?

Есть много ссылок на статьи, которые я написал на этой часто недопонимаемой теме.

Ответ 4

Самое интересное, что вы получите совершенно другой ответ с С++. Чистый компилятор.

int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1

Конечно, разница в результатах определяется другой семантикой - она ​​кажется нормальной. Но, несмотря на понимание того факта, что два компилятора .net не ведут себя аналогичным образом, такие основные вещи меня тоже путают.

Ответ 5

В этом примере

int x = 4;
x = x++ + ++x;

вы можете сломать его так:

x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10

Аналогично,

int x = 4;
x = x-- - --x;

Здесь

x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2

Проще говоря, вы можете сказать, замените текущее значение x, но для каждого ++ или - добавьте/вычтите значение из x.

Ответ 6

Я думаю, что объяснение для случая ++ + ++ неверно:

команда........... значение x

.................. неопределенными

int x = 4.......... 4

x ++............... 5 (первое слагаемое равно 4)

++ x............... 6 (второе слагаемое равно 6)

x = summand1 + summand2..4 + 6 = 10

Аналогичным объяснением для - - - случая является

команда........... значение x

.................. неопределенными

int x = 4.......... 4

x --............... 3 (subtactor is 4)

- x............... 2 (subtrahend is 2)

x = subtractor-subtrahend..4-2 = 10