ПрограммированиеVB.NET разработчик, Backend разработчик

Как работают циклы For Each в Visual Basic? В чем отличия от For и While, какие объекты можно перебрать таким образом и какие ловушки возникают при изменении коллекции в цикле?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Цикл For Each в Visual Basic предназначен для последовательного перебора всех элементов коллекции или массива. Его использование упрощает работу с перечисляемыми объектами (Collection, Array, списки и т.д.), не требуя явного обращения к индексам.

Синтаксис:

For Each element As DataType In collection ' Действия с element Next

Отличия от других циклов:

  • For — требует указания счетчика и диапазона, эффективен при необходимости доступа к элементам по индексу.
  • While — выполняется, пока условие истинно, пригоден для непредсказуемых количеств итераций.
  • For Each — итерирует по всем элементам без доступа к индексам, подходит для современных коллекций.

Ограничения и особенности For Each:

  • Нельзя напрямую изменять элементы коллекции (особенно если коллекция неизменяемая или структурная).
  • Коллекция должна реализовывать интерфейс IEnumerable.
  • При изменении коллекции (добавление/удаление элементов) во время цикла может возникнуть исключение InvalidOperationException.

Пример:

Dim items As New List(Of Integer)({1, 2, 3}) For Each item As Integer In items Console.WriteLine(item) Next

Попытка изменить коллекцию внутри цикла может вызвать ошибку:

For Each item As Integer In items If item = 2 Then items.Remove(item) ' Исключение! End If Next

Вопрос с подвохом

Можно ли изменять элементы коллекции по значению, используя For Each, если элементы — структуры?

Нет, если элементы коллекции — структуры (value types), то переменная-переборщик в For Each содержит копию значения. Любое изменение переменной не затронет настоящий элемент коллекции. Например:

Structure Point Public X As Integer End Structure Dim points As New List(Of Point)({New Point With {.X = 1}}) For Each pt In points pt.X = 100 ' Не изменяет points(0).X Next

Примеры реальных ошибок из-за незнания тонкостей темы


История

В проекте использовался For Each для изменения полей структур сотрудника. Итерация не изменяла исходные данные, потому что объект перебора был копией, а не самим элементом коллекции. Из-за этого обновление зарплат не срабатывало.


История

Во время перебора списка в For Each внутри условия удаляли элементы — в результате приложение выбрасывало InvalidOperationException и аварийно завершалось.


История

Перебор коллекции через For Each без учёта её изменяемости привел к бесконечному циклу, когда внешний источник данных наполнял эту коллекцию одновременно с её чтением, вызывая логические ошибки в расчётах.