Eric Lippert のブログと仕様によると、foreach ループは次のシンタックス シュガーです。
{
IEnumerator<string> e = ((IEnumerable<string>)new string[] { "pass1", "pass2", "pass3" }).GetEnumerator();
try
{
string pass; // OUTSIDE THE ACTUAL LOOP
while(e.MoveNext())
{
pass = (string)e.Current;
x = pass;
}
}
finally
{
if (e != null) ((IDisposable)e).Dispose();
}
}
ご覧のとおり、列挙子はループの前に作成されます。
@Rawling は正しく指摘しました。その配列はコンパイラによって少し異なって扱われました。foreachループは、配列を使用したforループに最適化されます。The Internals of C# foreach によると、C# 5 のコードは次のようになります。
string[] tempArray;
string[] array = new string[] { "pass1", "pass2", "pass3" };
tempArray = array;
for (string counter = 0; counter < tempArray.Length; counter++)
{
string pass = tempArray[counter];
x = pass;
}
初期化も一度だけ行われます。