Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Операторы итерации —
Операторы итерации многократно выполняют инструкцию или блок инструкций. Оператор for
выполняет текст, пока указанное логическое выражение вычисляется true
. Инструкция foreach
перечисляет элементы коллекции и выполняет его текст для каждого элемента коллекции. Оператор do
условно выполняет свой текст один или несколько раз. Оператор while
условно выполняет тело ноль или более раз.
В любой момент в тексте инструкции итерации можно выйти из цикла с помощью инструкцииbreak
. Вы можете перейти к следующей итерации в цикле с помощью инструкцииcontinue
.
Инструкция for
Оператор for
выполняет оператор или блок операторов, пока указанное логическое выражение вычисляется в true
. В следующем примере показан оператор for
, который выполняет его код, пока целочисленный счетчик меньше трех.
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
В предыдущем примере показаны элементы инструкции for
:
Раздел инициализатора , который выполняется только один раз перед вводом цикла. Как правило, вы объявляете и инициализируете локальную переменную цикла в этом разделе. Объявленная переменная не может быть доступна из-за пределов инструкции
for
.Раздел инициализатора в предыдущем примере объявляет и инициализирует целочисленную переменную счетчика:
int i = 0
Раздел условия , определяющий, следует ли выполнять следующую итерацию в цикле. Если значение равно
true
или отсутствует, выполняется следующая итерация; иначе цикл завершается. Раздел условия должен быть логическим выражением.Раздел условия в предыдущем примере проверяет, является ли значение счетчика меньше трех.
i < 3
Раздел итератора, определяющий, что происходит после каждого выполнения тела цикла.
Раздел итератора в предыдущем примере увеличивает счетчик:
i++
Тело цикла, которое должно быть операцией или блоком инструкций.
Раздел итератора может содержать ноль или более следующих выражений инструкций, разделенных запятыми:
-
префиксное или постфиксное инкрементное выражение, например
++i
илиi++
- выражение префиксного или постфиксного декремента, например
--i
илиi--
- задание
- вызов метода
-
await
Выражение - создание объекта с помощью
new
оператора
Если вы не объявляете переменную цикла в разделе инициализатора, можно также использовать ноль или больше выражений из предыдущего списка в разделе инициализатора. В следующем примере показано несколько менее распространенных вариантов использования инициализатора и итератора: назначение значения внешней переменной в разделе инициализатора, вызов метода в разделах инициализатора и итератора и изменение значений двух переменных в разделе итератора:
int i;
int j = 3;
for (i = 0, Console.WriteLine($"Start: i={i}, j={j}"); i < j; i++, j--, Console.WriteLine($"Step: i={i}, j={j}"))
{
//...
}
// Output:
// Start: i=0, j=3
// Step: i=1, j=2
// Step: i=2, j=1
Все разделы инструкции for
являются необязательными. Например, следующий код определяет бесконечный for
цикл:
for ( ; ; )
{
//...
}
Инструкция foreach
Инструкция foreach
выполняет инструкцию или блок инструкций для каждого элемента в экземпляре типа, реализующего System.Collections.IEnumerable или System.Collections.Generic.IEnumerable<T> интерфейс, как показано в следующем примере:
List<int> fibNumbers = new() { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibNumbers)
{
Console.Write($"{element} ");
}
// Output:
// 0 1 1 2 3 5 8 13
Оператор foreach
не ограничивается этими типами. Его можно использовать с экземпляром любого типа, удовлетворяющего следующим условиям:
- Тип имеет публичный метод без параметров
GetEnumerator
. ЭтотGetEnumerator
метод может быть методом расширения типа. - Возвращаемый тип метода
GetEnumerator
включает в себя общедоступное свойствоCurrent
и открытый методMoveNext
без параметров, чей возвращаемый тип —bool
.
В следующем примере используется foreach
инструкция с экземпляром System.Span<T> типа, который не реализует интерфейсы.
Span<int> numbers = [3, 14, 15, 92, 6];
foreach (int number in numbers)
{
Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6
Если свойство перечислителя Current
возвращает возвращаемое значение ссылки (ref T
где T
тип элемента коллекции), можно объявить переменную итерации с ref
ref readonly
модификатором, как показано в следующем примере:
Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
item = num++;
}
foreach (ref readonly var item in storage)
{
Console.Write($"{item} ");
}
// Output:
// 0 1 2 3 4 5 6 7 8 9
Если исходная коллекция инструкции foreach
пуста, текст инструкции foreach
не выполняется и пропускается. Если оператор foreach
применяется к null
, NullReferenceException выбрасывается исключение.
Оператор "await foreach"
Инструкцию await foreach
можно использовать для использования асинхронного потока данных, то есть типа коллекции, реализующего IAsyncEnumerable<T> интерфейс. Каждая итерация цикла может быть приостановлена, а следующий элемент извлекается асинхронно. В следующем примере показано, как использовать инструкцию await foreach
:
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
Инструкцию await foreach
можно также использовать с экземпляром любого типа, удовлетворяющего следующим условиям:
- Тип имеет публичный метод без параметров
GetAsyncEnumerator
. Этот метод может быть методом расширения типа. - Возвращаемый тип метода
GetAsyncEnumerator
имеет общедоступное свойствоCurrent
и открытый метод без параметровMoveNextAsync
, возвращаемый тип которого являетсяTask<bool>
,ValueTask<bool>
, или любой другой ожидающий тип, методGetResult
ожидающего возвращает значениеbool
.
По умолчанию элементы потока обрабатываются в захваченном контексте. Если вы хотите отключить запись контекста, используйте TaskAsyncEnumerableExtensions.ConfigureAwait метод расширения. Дополнительные сведения о контекстах синхронизации и записи текущего контекста см. в статье "Использование асинхронного шаблона на основе задач". Дополнительные сведения об асинхронных потоках см. в руководстве по асинхронным потокам.
Тип переменной итерации
Ключевое var
слово позволяет компилятору определить тип переменной итерации в foreach
инструкции, как показано в следующем коде:
foreach (var item in collection) { }
Замечание
var
Тип может быть выведен компилятором в качестве ссылочного типа, допускающего значение NULL, в зависимости от того, включен ли контекст с поддержкой NULL и является ли тип выражения инициализации ссылочным типом.
Дополнительные сведения см. в разделе неявно типизированные локальные переменные.
Можно также явно указать тип переменной итерации, как показано в следующем коде:
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
В предыдущей форме тип T
элемента коллекции должен быть неявно или явно преобразован в тип V
переменной итерации. Если при выполнении явное преобразование из T
в V
не удается, оператор foreach
вызывает исключение InvalidCastException. Например, если T
это непечатанный тип класса, может быть любой тип интерфейса, V
даже тот, который T
не реализует. Во время выполнения тип элемента коллекции может быть производным от T
и фактически реализующим V
. Если это не так, InvalidCastException выбрасывается исключение.
Инструкция do
Оператор do
выполняет оператор или блок операторов, пока указанное логическое выражение вычисляется в true
. Так как это выражение вычисляется после каждого выполнения цикла, do
цикл выполняется один или несколько раз. Цикл do
отличается от while
цикла, который выполняется один или более раз.
В следующем примере показано использование инструкции do
:
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
Инструкция while
Оператор while
выполняет оператор или блок операторов, пока указанное логическое выражение вычисляется в true
. Так как это выражение вычисляется перед каждым выполнением цикла, while
цикл выполняется от нуля и более раз. Цикл while
отличается от do
цикла, который выполняется один или несколько раз.
В следующем примере показано использование инструкции while
:
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
Дополнительные сведения об этих функциях см. в следующих заметках о предложении функций:
См. также
- декларации
- итераторы