ILDasm有时可能是你最好的朋友 ;-)
我编译了两种方法并比较了它们生成的IL(汇编语言)。
不出所料,重要的细节在循环中。第一种方法的编译和运行方式如下:
Code Description Stack
ldloc.1 Load ref to newArray2 newArray2
ldloc.2 Load value of IndTmp newArray2,0
ldloc.0 Load ref to newArray1 newArray2,0,newArray1
ldloc.2 Load value of IndTmp newArray2,0,newArray1,0
dup Duplicate top of stack newArray2,0,newArray1,0,0
ldc.i4.1 Load 1 newArray2,0,newArray1,0,0,1
add Add top 2 values on stack newArray2,0,newArray1,0,1
stloc.2 Update IndTmp newArray2,0,newArray1,0 <-- IndTmp is 1
ldelem.ref Load array element newArray2,0,"1"
stelem.ref Store array element <empty>
<-- newArray2[0] = "1"
这对于newArray1中的每个元素都会重复执行。重要的是,在增加IndTmp之前,源数组中元素的位置已被推入堆栈。
将其与第二种方法进行比较:
Code Description Stack
ldloc.1 Load ref to newArray2 newArray2
ldloc.2 Load value of IndTmp newArray2,0
dup Duplicate top of stack newArray2,0,0
ldc.i4.1 Load 1 newArray2,0,0,1
add Add top 2 values on stack newArray2,0,1
stloc.2 Update IndTmp newArray2,0 <-- IndTmp is 1
ldloc.0 Load ref to newArray1 newArray2,0,newArray1
ldloc.2 Load value of IndTmp newArray2,0,newArray1,1
ldelem.ref Load array element newArray2,0,"2"
stelem.ref Store array element <empty>
<-- newArray2[0] = "2"
这里的IndTmp在源数组中的位置被推入栈之前已经自增了,因此导致行为不同(并引发后续异常)。
为了完整起见,让我们与之进行比较:
newArray2[IndTmp] = newArray1[++IndTmp];
Code Description Stack
ldloc.1 Load ref to newArray2 newArray2
ldloc.2 Load IndTmp newArray2,0
ldloc.0 Load ref to newArray1 newArray2,0,newArray1
ldloc.2 Load IndTmp newArray2,0,newArray1,0
ldc.i4.1 Load 1 newArray2,0,newArray1,0,1
add Add top 2 values on stack newArray2,0,newArray1,1
dup Duplicate top stack entry newArray2,0,newArray1,1,1
stloc.2 Update IndTmp newArray2,0,newArray1,1 <-- IndTmp is 1
ldelem.ref Load array element newArray2,0,"2"
stelem.ref Store array element <empty>
<-- newArray2[0] = "2"
在这里,增量操作的结果先被推入栈中(并成为数组的索引),然后再更新IndTmp的值。
总之,赋值语句的目标似乎是先被评估,接着才是源。
感谢原帖作者提出这个非常发人深思的问题!
newArray1[IndTmp ++]
之前要评估newArray2[IndTmp]
?” 这是一个很好的问题,这必须意味着赋值的目标(LHS)在被赋值的值(RHS)之前得到评估。这似乎是更直观的行为,但如果规范似乎表明不同,那么我会对此感兴趣。值得一提的是,LHS引用一个变量,而RHS处理要分配给该变量的值。 - Justin Morgan