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 更新之前,增量的结果已被推送到堆栈(并成为数组索引)。
总而言之,似乎是首先评估分配的目标,然后是源。
向OP竖起大拇指,提出一个真正发人深省的问题!