I have an array of structs. Does foreach
operator make a copy of each element when iterating thru an array? As far as I understand foreach
is just syntactic sugar under the hood converted to for
. So it appears the answer is no but I'd love to have some confirmation.
PS: it appears someone should have already asked that but I can't easily find anything. So please vote as a dup with provided reference.
forEach() does not make a copy of the array before iterating.
forEach() does not mutate the array on which it is called. (However, callback may do so).
Very often we simply know the size of the array. We can then just use a normal for loop to iterate over the contents. The sizeof(data)/sizeof(data[0]) calculates the amount of elements: gets the total size of an array and divides it by the size of a single element. This method has its drawbacks.
How Does It Work? The foreach loop in C# uses the 'in' keyword to iterate over the iterable item. The in keyword selects an item from the collection for the iteration and stores it in a variable called the loop variable, and the value of the loop variable changes in every iteration.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With