Оператор For Each производит перечисление элементов коллекции при этом выполняя блок вложенных операторов для каждого элемента коллекции.
foreach-statement:
For Each identifier In expression Do statement-listopt End For
В каждом операторе For Each указывается идентификатор переменной, которая называется переменной цикла. Во время выполнения оператора переменная цикла представляет элемент коллекции для которого в текущий момент производится итерация. Ошибка компиляции выдается в случае если вложенный оператор пытается изменить значение переменной цикла или передать ее в качестве значения параметра по ссылке.
Выражение в операторе (его тип) должно представлять собою коллекцию и должно быть определено явное преобразование от типа элементов коллекции к типу переменной цикла. Если значение выражения в операторе равно Null, то возбуждается исключительная ситуация типа System.NullReferenceException.
Тип C может быть назван типом-коллекцией если он реализует интерфейс System.Collections.IEnumerable или шаблон коллекции, удовлетворяя всем нижеперечисленным условиям:
Тип С содержит открытый экземплярный метод GetEnumerator ,который не имеет параметров и возвращает значение типа класс, интерфейс или структура,который называется E далее по тексту.
Тип E содержит открытый экземплярный метод MoveNext, который не имеет параметров и возвращает значение типа Boolean.
Тип E содержит открытое экземплярное свойство Current, которое допускает чтение текущего значения. Тип этого свойства называется типом элементов коллекции.
Системный тип System.Array также является типом-коллекцией. Поскольку все массивы являются производными от данного типа, то в операторе For Each допускается использование любого выражения, являющегося массивом. Порядок обхода элементов массива определяется следующим образом. Если массив является одномерным, то его элементы обходятся в порядке увеличения индекса от наименьшего к наибольшему. Если массив является многомерным, то его элементы обходятся таким образом чтобы в первую очередь увеличивались индексы самого правого измерения (последнего), а в последнюю очередь самого левого (первого).
Оператор For Each в следующей форме:
For Each element In collection Do statement End For
соответствует одному из двух возможных развертываний:
Если выражение имеет тип, реализующий шаблон коллекции (как определено выше), то оператор развертывается следующим образом:
Var
enumerator: E;
element: ElementType
disposable: IDisposable;
…
enumerator := (collection).GetEnumerator;
Try
While enumerator.MoveNext Do
element := enumerator.Current As ElementType;
statement;
End While
Finally
disposable := enumerator as System.IDisposable;
If disposable <> Null
disposable.Dispose;
End If
End Try
В противном случае если выражение является типом, реализующим интерфейс, то оно развертывается следующим образом:
Var
enumerator: IEnumerator;
element: ElementType
disposable: IDisposable;
…
enumerator := ((collection) As System.Collections.IEnumerable).GetEnumerator;
Try
While enumerator.MoveNext Do
element := enumerator.Current As ElementType;
statement;
End While
Finally
disposable := enumerator as System.IDisposable;
If disposable <> Null
disposable.Dispose;
End If
End Try
Private Sub TestForEach();
Var
s: Array Of string;
s1: string;
Begin
For Each s1 In s Do
//Операции с s1
End For;
End Sub;
См. также: