Пре - и пост-инкремент в C#


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

когда я код ниже:

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

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

но когда я код:

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

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

6 60

6 ответов:

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

x = 4 - 2

Кстати, Ваш первый случай будет 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

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

IL_0002:  ldloc.0     

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

IL_0003:  dup         

дублирует верхний элемент в стеке. Стек => (4, 4)

IL_0004:  ldc.i4.1    

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

IL_0005:  sub         

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

IL_0006:  stloc.0     

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

IL_0007:  ldloc.0     

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

IL_0008:  ldc.i4.1    

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

IL_0009:  sub         

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

IL_000A:  dup         

дублировать верхнее значение => (2, 2, 4)

IL_000B:  stloc.0     

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

IL_000C:  sub      

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

IL_000D:  stloc.0  

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

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

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

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

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

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

в чем разница между I++ и ++I?

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

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

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

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

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

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.

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

...........значение x

..................неопределенный

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

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

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

x=слагаемое 1+слагаемое 2 ..4+6=10

аналогичное объяснение для -- - -- случая

...........стоимость x

..................неопределенный

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

x--...............3 (subtactor является 4)

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

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