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
。 任何人都可以解释为什么会这样吗?
x--
将是4,但是在--x
时刻将是3,所以它将结束为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。 堆栈=>(2,4)
IL_000C: sub
减去两个最高值。 堆栈=>(2)
IL_000D: stloc.0
将此值存储回x。 x == 2
从你的评论:
我认为在评估完整代码行之后/之前执行后增量和前增量 – 但是它们在表达式中每个项目的评估之后/之前执行。
你的误解是一个非常普遍的误解。 请注意,在某些语言(如C)中,当副作用变得可见时未指定,因此在C语句中您的语句为真,因此它是合法的,但不是必需的。
在C#中并非如此; 在C# 中,表达式左侧代码的副作用始终被观察到在右侧代码执行之前 (来自单个线程;在multithreading场景中,所有投注都关闭。)
有关增量运算符在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 = summand1 + summand2 ..4 + 6 = 10
类似于 – – – 案例的解释是
命令………..x的值
………………未定义
int x = 4 ………. 4
x – ………… 3(子接收器为4)
–x …………… 2(减数为2)
x =减法器 – 减数..4-2 = 10