次の方法で共有


イテレーション ステートメント - forforeachdo、および while

反復ステートメントは、ステートメントまたはステートメントのブロックを繰り返し実行します。 for ステートメントは、指定されたブール式がtrue評価される間、その本体を実行します。 foreach ステートメントは、コレクションの要素を列挙し、コレクションの各要素の本体を実行します。 do ステートメントは、本体を 1 回以上条件付きで実行します。 while ステートメントは、本体を 0 回以上条件付きで実行します。

反復ステートメントの本体内の任意の時点で、 break ステートメントを使用してループから抜け出すことができます。 continue ステートメントを使用して、ループ内の次のイテレーションにステップ インできます。

for ステートメント

for ステートメントはステートメントまたはステートメント ブロックを実行しますが、指定されたブール式はtrueと評価されます。 次の例は、整数カウンターが 3 未満の場合に本体を実行する for ステートメントを示しています。

for (int i = 0; i < 3; i++)
{
    Console.Write(i);
}
// Output:
// 012

前の例は、 for ステートメントの要素を示しています。

  • ループに入る前に 1 回だけ実行される 初期化子 セクション。 通常は、そのセクションでローカル ループ変数を宣言して初期化します。 宣言された変数は、 for ステートメントの外部からアクセスできません。

    前の例の 初期化子 セクションでは、整数カウンター変数を宣言して初期化します。

    int i = 0
    
  • ループ内の次の反復を実行する必要があるかどうかを決定する 条件 セクション。 trueに評価された場合、または存在しない場合は、次のイテレーションが実行されます。それ以外の場合は、ループが終了します。 条件セクションはブール式である必要があります。

    前の例の condition セクションでは、カウンター値が 3 未満かどうかを確認します。

    i < 3
    
  • ループ本体の各実行後の動作を定義する 反復子 セクション。

    前の例の 反復子 セクションは、カウンターをインクリメントします。

    i++
    
  • ループの本体。ステートメントまたはステートメントのブロックである必要があります。

iterator セクションには、次のステートメント式のうち 0 個以上をコンマで区切って含めることができます。

初期化子セクションでループ変数を宣言しない場合は、初期化子セクションの前のリストの 0 個以上の式を使用することもできます。 次の例は、初期化子セクションと反復子セクションのあまり一般的でない使用法をいくつか示しています。初期化子セクションの外部変数に値を割り当てる、初期化子セクションと反復子セクションの両方でメソッドを呼び出す、反復子セクションで 2 つの変数の値を変更する、

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>、または awaiter の 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 ループは 1 回以上実行されます。 do ループは、0 回以上実行されるwhile ループとは異なります。

次の例は、 do ステートメントの使用方法を示しています。

int n = 0;
do
{
    Console.Write(n);
    n++;
} while (n < 5);
// Output:
// 01234

while ステートメント

while ステートメントはステートメントまたはステートメント ブロックを実行しますが、指定されたブール式はtrueと評価されます。 その式はループの各実行前に評価されるため、 while ループは 0 回以上実行されます。 while ループは、1 回以上実行されるdo ループとは異なります。

次の例は、 while ステートメントの使用方法を示しています。

int n = 0;
while (n < 5)
{
    Console.Write(n);
    n++;
}
// Output:
// 01234

C# 言語仕様

詳細については、「C# 言語仕様」の次のセクションを参照してください。

これらの機能の詳細については、機能の提案に関する次の記述を参照してください。

こちらも参照ください