Yes, copies of the value type instances will be made. When iterating over an array, foreach
will indeed use array accesses instead of using an enumerator, but the value in each array slot is still copied.
This code:
struct AStruct
{
public string a;
public int b;
static void Main()
{
var structs = new AStruct[10];
foreach (var x in structs) {
Console.WriteLine(x);
}
}
}
Generates the following IL for the Main()
method:
.method private static hidebysig
default void Main () cil managed
{
.entrypoint
.maxstack 4
.locals init (
valuetype AStruct[] V_0,
valuetype AStruct[] V_1,
int32 V_2,
valuetype AStruct V_3)
IL_0000: ldc.i4.s 0x0a
IL_0002: newarr AStruct
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: stloc.1
IL_000a: ldc.i4.0
IL_000b: stloc.2
IL_000c: br IL_002d
IL_0011: ldloc.1
IL_0012: ldloc.2
IL_0013: ldelema AStruct
IL_0018: ldobj AStruct
IL_001d: stloc.3
IL_001e: ldloc.3
IL_001f: box AStruct
IL_0024: call void class [mscorlib]System.Console::WriteLine(object)
IL_0029: ldloc.2
IL_002a: ldc.i4.1
IL_002b: add
IL_002c: stloc.2
IL_002d: ldloc.2
IL_002e: ldloc.1
IL_002f: ldlen
IL_0030: conv.i4
IL_0031: blt IL_0011
IL_0036: ret
} // end of method AStruct::Main
Note the instructions IL_0013 through IL_001d. The entire value at each array slot is pushed onto the stack and stored in the local V_3 (the x
iteration variable).