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 がインクリメントされる前に、ソース配列内の要素の位置がスタックにプッシュされていることです。
これを 2 番目の方法と比較します。
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に賛成です!