First, even worrying about this is a micro-optimization; you shouldn't worry about it until you are studying the performance of your application and profiling suggests that this method and this loop are bottlenecks. Second, yes the compiler will reuse the same instance of the local variables re
and ddl
.
Here's a very simple example:
class Program {
static void Main(string[] args) {
string[] strings = new [] { "hello", "world" };
foreach (string s in strings) {
int i = s.Length;
}
return;
}
}
Here's the IL:
.method private hidebysig static void Main(string[] args) cil managed {
.entrypoint
.maxstack 3
.locals init (
[0] string[] strings,
[1] string s,
---> [2] int32 i,
[3] string[] CS$0$0000,
[4] string[] CS$6$0001,
[5] int32 CS$7$0002,
[6] bool CS$4$0003)
L_0000: nop
L_0001: ldc.i4.2
L_0002: newarr string
L_0007: stloc.3
L_0008: ldloc.3
L_0009: ldc.i4.0
L_000a: ldstr "hello"
L_000f: stelem.ref
L_0010: ldloc.3
L_0011: ldc.i4.1
L_0012: ldstr "world"
L_0017: stelem.ref
L_0018: ldloc.3
L_0019: stloc.0
L_001a: nop
L_001b: ldloc.0
L_001c: stloc.s CS$6$0001
L_001e: ldc.i4.0
L_001f: stloc.s CS$7$0002
L_0021: br.s L_0038
L_0023: ldloc.s CS$6$0001
L_0025: ldloc.s CS$7$0002
L_0027: ldelem.ref
L_0028: stloc.1
L_0029: nop
L_002a: ldloc.1
--->L_002b: callvirt instance int32 [mscorlib]System.String::get_Length()
--->L_0030: stloc.2
L_0031: nop
L_0032: ldloc.s CS$7$0002
L_0034: ldc.i4.1
L_0035: add
L_0036: stloc.s CS$7$0002
L_0038: ldloc.s CS$7$0002
L_003a: ldloc.s CS$6$0001
L_003c: ldlen
L_003d: conv.i4
L_003e: clt
L_0040: stloc.s CS$4$0003
L_0042: ldloc.s CS$4$0003
L_0044: brtrue.s L_0023
L_0046: br.s L_0048
L_0048: ret
}
Notice that in the locals section, the variable i
is declared as occupying the second location on the stack and this is where the result of get_Length
is repeatedly being stored on each iteration through the loop. (I have highlighted the relevant lines with --->
s in the margin.)