迭代语句重复执行语句或语句块。for 语句:在指定的布尔表达式的计算结果为 true 时会执行其主体。foreach 语句:枚举集合元素并对集合中的每个元素执行其主体。do 语句:有条件地执行其主体一次或多次。while 语句:有条件地执行其主体零次或多次。

在迭代语句体中的任何点,都可以用 break 语句跳出循环;可以用 continue 语句进入循环中的下一个迭代;可以用 return 语句返回值并退出整个迭代;可以用 goto 跳转到其他标签。

for 语句

在指定的 bool 表达式的计算结果为 true 时,for 语句会执行一条语句或一个语句块。以下示例显示了 for 语句,该语句在整数计数器小于 3 时执行其主体:

for ( int i = 0 ; i < 3 ; i++ )
{
    Console.Write ( $"{i}    " );
}
// 输出:
// 0    1    2    

上述示例展示了 for 语句的元素:

  • “初始化表达式”部分仅在进入循环前执行一次。 通常,在该部分中声明并初始化局部循环变量。 不能从 for 语句外部访问声明的变量。
    上例中的“初始化表达式”部分声明并初始化整数计数器变量:
    int i = 0
  • “条件”部分确定是否应执行循环中的下一个迭代。如果计算结果为 true 或不存在,则执行下一个迭代;否则退出循环。“条件”部分必须为布尔表达式。
    上例中的“条件”条件部分检查计数器值是否小于 3:
    i < 3
  • “迭代器”部分定义循环主体的每次执行后将执行的操作。
    上例中的“迭代器”部分增加计数器:
    i++
  • 循环体,必须是一个语句或一个语句块。

“迭代器”部分可包含用逗号分隔的零个或多个以下语句表达式:

  • 为 increment(递增)表达式添加前缀或后缀,如 ++i 或 i++
  • 为 decrement(递减)表达式添加前缀或后缀,如 --i 或 i--
  • assignment(赋值)
  • 方法的调用
  • await 表达式
  • 通过使用 new 运算符来创建对象

如果未在“初始化表达式”部分中声明循环变量,则还可以在“初始化表达式”部分中使用上述列表中的零个或多个表达式。下面的示例显示了几种不太常见的“初始化表达式”和“迭代器”部分的使用情况:为“初始化表达式”部分中的外部变量赋值、同时在“初始化表达式”部分和“迭代器”部分中调用一种方法,以及更改“迭代器”部分中的两个变量的值:

int i;
int j = 3;
for ( i = 0 , Console . WriteLine ( $"起始:i = {i},j = {j}" ) ; i < j ; i++ , j-- , Console . WriteLine ( $"步数:i = {i},j = {j}" ) )
{
    // ……
}
// 输出:
// 起始:i = 0,j = 3
// 步数:i = 1,j = 2
// 步数:i = 2,j = 1

for 语句的所有部分都是可选的。 例如,以下代码定义无限 for 循环:

for ( ; ; )
{
    // ……
}

for 语句对于数组或队列中的元素,是根据指定的“初始化表达式”、“条件”和“迭代器”来确定是否进行下一次循环以及下一个处理的元素的索引的。因此,for 循环体可能一次也不被执行(初始化表达式与条件不符);不是每次都执行(迭代器确定)等。

List < int > Zhss = [ 1 , 2 , 3 , 4 , 5 ];
for ( int i = 0 ; i < Zhss . Count ; i++ ) // i++ 相当于 i += 1
    {
    Console . Write ( Zhss[ i ] );
    }

将输出:
12345

List < int > Zhss = [ 1 , 2 , 3 , 4 , 5 ];
for ( int i = 0 ; i < Zhss . Count ; i += 2 ) // for 循环仅处理偶数索引的元素(0、2、4 个)
    {
    Console . Write ( Zhss[ i ] );
    }

将输出:
135

foreach 语句

foreach 语句为实现 System . Collections . IEnumerable 或 System . Collections . Generic . IEnumerable < T > 接口的类型实例中的每个元素执行一个语句或一个语句块,示例如下:

List < int > NumFib = 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 > Zhss = [ 3 , 14 , 15 , 92 , 6];
foreach ( int z in Zhss )
    {
    Console . Write ( $"{z}    " );
    }

上例输出:
3 14 15 92 6

如果枚举数的 Current 属性返回一个引用返回值(ref T,其中 T 是一个集合元素的类型),你可以用 ref 或 ref readonly 修饰符声明一个迭代变量,如下例所示:

Span < int > 十个数 = stackalloc int [ 10 ];
int num = 0;
foreach ( ref int xm in 十个数 )
    {
    xm = num++;
    }
foreach ( ref readonly var xm in 十个数 )
    {
    Console . Write ( $"{xm} " );
    }

上例输出:
0 1 2 3 4 5 6 7 8 9

如果 foreach 语句的源集合为空,则不执行并跳过 foreach 语句的主体。如果 foreach 语句应用于 null,则抛出 NullReferenceException。

await foreach

您可以使用 await foreach 语句来使用异步数据流,即实现 IAsyncEnumerable < T > 接口的集合类型。在异步检索下一个元素时,循环的每次迭代都可能被挂起。

你也可以对满足以下条件的任何类型的实例使用 await foreach 语句:

  • 类型具有公共无参数的 GetAsyncEnumerator 方法。该方法可以是类型的扩展方法。
  • GetAsyncEnumerator 方法的返回类型具有公共 Current 属性和公共无参数 MoveNextAsync 方法,其返回类型为 Task < bool >、ValueTask < bool > 或任何其他可等待类型,其 awaiter 的 GetResult 方法返回 bool 值。

默认情况下,在捕获的上下文中处理流元素。如果您想禁用上下文捕获,请使用 TaskAsyncEnumerableExtensions . ConfigureAwait 扩展方法。

迭代变量的类型

你可以使用 var 关键字让编译器在 foreach 语句中推断迭代变量的类型,如下面的代码所示:
foreach ( var 项目 in 集合 ) { }

请注意:var 的类型可以被编译器推断为可空的引用类型,具体取决于是否启用了可空的上下文,以及初始化表达式的类型是否为引用类型。

你也可以显式指定迭代变量的类型,如下面的代码所示:

IEnumerable < T > collection = new T [ 5 ];
foreach ( V 项目 in 集合 ) { }

在上例的形式中,集合元素的类型 T 必须隐式或显式地转换为迭代变量的类型 V。如果从 T 到 V 的显式转换在运行时失败,则 foreach 语句抛出 InvalidCastException。例如,如果 T 是一个非密封类类型,那么 V 可以是任何接口类型,甚至是 T 没有实现的接口类型。在运行时,集合元素的类型可能是派生自 T 并实际实现 V 的类型。如果不是这种情况,则抛出 InvalidCastException。

do 语句

当指定的布尔表达式求值为 true 时,do 语句执行一条语句或语句块。因为该表达式在每次循环执行后求值,所以 do 循环执行一次或多次。do 循环不同于 while 循环,后者执行零次或多次。

下面的例子展示了 do 语句的用法:

int n = 0;
do
{
    Console . Write ( $"{n}    ");
    n++;
} while ( n < 5 );
// 输出:
// 0    1    2    3    4    

while 语句

while 语句执行一条语句或语句块,而指定的布尔表达式的计算结果为 true。因为该表达式在每次循环执行之前求值,所以 while 循环执行零次或多次。while 循环不同于 do 循环,后者执行一次或多次。

下面的例子展示了 while 语句的用法:

int n = 0;
while ( n < 5 )
{
    Console . Write ( $"{n}    " );
    n++;
}
// 输出:
// 0    1    2    3    4    

兔子码农
3 声望1 粉丝

一个酒晕子