Пре - и пост-инкремент в 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 ответов:
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