Два фрагмента кода выдают точно один и тот же IL. Вот код C #, с которым я тестировал:
public string[] strings = new string[5];
public void TestOne()
{
foreach (string s in strings)
{
string t = s;
}
}
public void TestTwo()
{
string t;
foreach (string s in strings)
{
t = s;
}
}
А вот итоговый IL для обоих методов после компиляции с включенной оптимизацией:
.method public hidebysig instance void TestOne() cil managed
{
// Code size 26 (0x1a)
.maxstack 2
.locals init ([0] string s,
[1] string[] CS$6$0000,
[2] int32 CS$7$0001)
IL_0000: ldarg.0
IL_0001: ldfld string[] strings
IL_0006: stloc.1
IL_0007: ldc.i4.0
IL_0008: stloc.2
IL_0009: br.s IL_0013
IL_000b: ldloc.1
IL_000c: ldloc.2
IL_000d: ldelem.ref
IL_000e: stloc.0
IL_000f: ldloc.2
IL_0010: ldc.i4.1
IL_0011: add
IL_0012: stloc.2
IL_0013: ldloc.2
IL_0014: ldloc.1
IL_0015: ldlen
IL_0016: conv.i4
IL_0017: blt.s IL_000b
IL_0019: ret
} // end of method TestOne
.method public hidebysig instance void TestTwo() cil managed
{
// Code size 26 (0x1a)
.maxstack 2
.locals init ([0] string s,
[1] string[] CS$6$0000,
[2] int32 CS$7$0001)
IL_0000: ldarg.0
IL_0001: ldfld string[] strings
IL_0006: stloc.1
IL_0007: ldc.i4.0
IL_0008: stloc.2
IL_0009: br.s IL_0013
IL_000b: ldloc.1
IL_000c: ldloc.2
IL_000d: ldelem.ref
IL_000e: stloc.0
IL_000f: ldloc.2
IL_0010: ldc.i4.1
IL_0011: add
IL_0012: stloc.2
IL_0013: ldloc.2
IL_0014: ldloc.1
IL_0015: ldlen
IL_0016: conv.i4
IL_0017: blt.s IL_000b
IL_0019: ret
} // end of method TestTwo
Как обычно, правило такое же: доверяйте своему компилятору . Пусть он обрабатывает эти оптимизации для вас, а не пытается беспокоиться об этом, когда вы пишете код. Просто напишите код, который имеет смысл и доступен для чтения.
Самое главное, игнорировать всех людей, которые утверждают, что один из них "теоретически" лучше другого. Это полная чушь. Там нет теории, которая актуальна до тех пор, пока код не скомпилирован. И поскольку он компилируется в одно и то же, он гарантированно полностью идентичен по производительности.
Но если вы все еще не верите моим убеждениям доверять вашему компилятору (некоторые из нас упрямы, я знаю, потому что даже я иногда так и есть), по крайней мере, теперь вы знаете, как ответить на эти вопросы самостоятельно. Напишите пример кода, демонстрирующий оба варианта, скомпилируйте его в режиме «Release», затем откройте сборку в ILDASM.exe и сравните полученный код IL для себя. Такие вещи очень легко проверить, и нет никаких оснований угадывать.