Преобразует ли foreach каждый элемент, если он является массивом структур?

У меня есть массив структур. Оператор foreach создает копию каждого элемента при итерации по массиву? Насколько я понимаю, foreach - это просто синтаксический сахар под капотом, преобразованный в for. Таким образом, кажется, что ответ - нет, но я хотел бы получить подтверждение.

PS: кажется, кто-то должен был уже спросить об этом, но я не могу легко найти что-либо. Поэтому, пожалуйста, проголосуйте за дубликата с предоставленной ссылкой.

1 ответ

Да, будут сделаны копии экземпляров типа значения. При итерации по массиву foreach действительно будет использовать обращения к массиву вместо использования счетчика, но значение в каждом слоте массива все еще копируется.

Этот код:

struct AStruct
{
 public string a;
 public int b;
 static void Main()
 {
 var structs = new AStruct[10];
 foreach (var x in structs) {
 Console.WriteLine(x);
 }
 }
}

Создает следующий IL для метода Main():

.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

Обратите внимание на инструкции IL_0013 по IL_001d. Все значение в каждом слоте массива помещается в стек и сохраняется в локальной V_3 (переменная итерации x).

licensed under cc by-sa 3.0 with attribution.