Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Tip
Эта статья является частью раздела "Основы" для разработчиков , которые уже знают хотя бы один язык программирования и учат C#. Если вы не знакомы с программированием, сначала начните с учебных пособий по началу работы. Полное описание синтаксиса см. в разделе операторы итерации в справочнике по языку.
Вы пришли из другого языка? Все четыре цикла C# (foreach, , whiledo-whileиfor) имеют прямые эквиваленты в Java, C++и JavaScript. Чаще всего используется foreach . Он перебирает элементы коллекции без использования индекса, как расширенный for в Java или for...of в JavaScript.
Операторы итерации многократно выполняют блок кода. Каждый проход через блок является итерацией, и повторяющийся блок является циклом. C# предоставляет четыре цикла. Начните с foreach для коллекций, используйте while и do-while, когда повторение определяется условием, и используйте for, когда нужен явный индекс.
Итерации коллекции с помощью foreach
Инструкция foreach выполняет тело по одному разу для каждого элемента коллекции по порядку. Это наиболее распространенный выбор для чтения коллекции, так как вы не управляете индексом или проверкой границ. Инструкция foreach предотвращает типичные ошибки на единицу:
string[] names = ["Ana", "Ben", "Cleo"];
// foreach reads each element in order. It's the default loop for
// collections: no index to manage and no off-by-one mistakes.
foreach (string name in names)
{
Console.WriteLine(name); // => Ana, then Ben, then Cleo
}
foreach работает с любым типом, который C# распознает как последовательность, включая массивы, List<T>и Dictionary<TKey,TValue>. Переменная итерации (name в предыдущем примере) доступна только для чтения, поэтому ее нельзя переназначить внутри цикла.
Текст цикла — это одна инструкция, например назначение или вызов метода.
Блочная инструкция сама по себе является одной инструкцией, которая заключает в фигурные скобки ({ }) ноль или более инструкций.
Многие стандарты программирования рекомендуют заключать текст цикла в фигурные скобки даже для одной инструкции. Фигурные скобки явно задают область видимости. Это предотвращает распространённую ошибку: если позже добавить вторую строку, которую, как ожидается, будут выполнять на каждой итерации, она вместо этого выполнится один раз после завершения цикла. Только фигурные скобки определяют, какие операторы принадлежат циклу. C# не считает пробельные символы значимыми, поэтому сами по себе отступы тоже никогда не имеют значения. Фигурные скобки допустимы даже для одной строки кода: блок представляет собой единственную инструкцию, которую цикл повторяет. Используйте отступы в коде для удобочитаемости, но определяйте блок с помощью фигурных скобок.
Повторять, пока условие выполняется с while
Цикл while проверяет логическое условие перед каждой итерацией. Если условие false в начале, тело цикла ни разу не выполняется, поэтому цикл while выполняется ноль или более раз:
int countdown = 3;
// A while loop checks its condition before each iteration, so the body
// runs zero or more times.
while (countdown > 0)
{
Console.WriteLine(countdown); // => 3, then 2, then 1
countdown--;
}
Убедитесь, что что-то внутри цикла изменяет условие. В предыдущем примере countdown-- в конечном итоге приводит условие к виду false. Цикл, условие которого никогда не становится false, выполняется бесконечно.
Запуск текста по крайней мере один раз с do-while
Цикл do-while проверяет своё условие после каждой итерации, поэтому тело всегда выполняется хотя бы один раз. Используйте его, когда первый проход должен произойти, прежде чем вы сможете оценить условие, например запрашивать входные данные, а затем проверять его:
int attempts = 0;
// A do-while loop runs its body once, then checks the condition. Use it
// when the body must run at least one time.
do
{
attempts++;
Console.WriteLine($"Attempt {attempts}"); // => Attempt 1, then Attempt 2, then Attempt 3
}
while (attempts < 3);
Считайте с помощью for
Оператор for цикла содержит три части: инициализатор , который запускается один раз перед циклом, условие , которое проверяется перед каждой итерацией, итератор , который выполняется после каждой итерации. Используйте for, когда нужен сам индекс, а не только элементы. Как правило, требуется индекс, когда нужно изменить элемент, а не считывать его значение.
// A for loop fits when you need an explicit index. The three parts are
// the initializer, the condition, and the iterator.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i); // => 0, then 1, then 2
}
Если вы только читаете элементы и не используете позиции и не присваиваете новые значения, используйте foreach. Он указывает намерение более четко и избегает арифметики индекса.
Выход или пропуск с помощью break и continue
Два оператора перехода обеспечивают более точное управление в любом цикле. Оператор break немедленно завершает цикл, пропуская все оставшиеся итерации:
int[] numbers = [2, 4, 7, 8];
// break stops the loop immediately, skipping any remaining elements.
foreach (int number in numbers)
{
if (number % 2 != 0)
{
Console.WriteLine($"First odd number: {number}"); // => First odd number: 7
break;
}
}
Оператор continue пропускает остальную часть текущей итерации и переходит к следующей:
int[] values = [1, 2, 3, 4, 5];
// continue skips the rest of the current iteration and moves to the next.
foreach (int value in values)
{
if (value % 2 == 0)
{
continue; // skip even numbers
}
Console.WriteLine(value); // => 1, then 3, then 5
}
Итерацию асинхронного потока с помощью await foreach
Асинхронный поток — это средство чтения, использующее асинхронную задачу для создания каждого следующего элемента. В C# это представлено интерфейсом IAsyncEnumerable<T>. Данные, поступающие с течением времени, такие как страницы из веб-API или строк из базы данных, соответствуют этой модели: извлечение следующего элемента является ожидаемой операцией вместо немедленного возврата.
Чтобы перебирать асинхронный поток, поставьте ключевое слово await перед foreach. Каждая итерация ожидает следующего элемента, поэтому цикл приостанавливается во время создания этого элемента, а не блокирует поток:
private static async Task AwaitForeachExample()
{
// await foreach consumes an asynchronous stream. Each iteration can
// suspend while the next element is produced.
await foreach (int value in GenerateAsync())
{
Console.WriteLine(value); // => 0, then 1, then 2
}
}
private static async IAsyncEnumerable<int> GenerateAsync()
{
for (int i = 0; i < 3; i++)
{
await Task.Delay(1); // stand-in for real asynchronous work
yield return i;
}
}
Асинхронные потоки основаны на async и await. Полное пошаговое руководство см. в разделе "Создание и использование асинхронных потоков".