Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does foreach copy each element if it is an array of structs?

Tags:

c#

.net

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.

like image 510
Schultz9999 Avatar asked Jan 18 '13 21:01

Schultz9999


People also ask

Does forEach make a copy of the array?

forEach() does not make a copy of the array before iterating.

Does forEach mutate array?

forEach() does not mutate the array on which it is called. (However, callback may do so).

How do you iterate an array of structs?

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 do forEach loops work?

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.


1 Answers

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).

like image 66
cdhowie Avatar answered Sep 23 '22 20:09

cdhowie