次の方法で共有


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

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

反復ステートメントの本体内の任意の時点で、 break ステートメントを使用してループを終了できます。 continue ステートメントを使用して、ループ内の次のイテレーションにステップ インできます。

C# 言語リファレンスには、C# 言語の最新リリース バージョンが記載されています。 また、今後の言語リリースのパブリック プレビューの機能に関する初期ドキュメントも含まれています。

このドキュメントでは、言語の最後の 3 つのバージョンまたは現在のパブリック プレビューで最初に導入された機能を特定します。

ヒント

C# で機能が初めて導入された時期を確認するには、 C# 言語バージョン履歴に関する記事を参照してください。

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 値を返すその他の待機可能型のいずれかです。

既定では、 await foreach ステートメントはキャプチャされたコンテキスト内のストリーム要素を処理します。 コンテキストのキャプチャを無効にする場合は、 TaskAsyncEnumerableExtensions.ConfigureAwait 拡張メソッドを使用します。 同期コンテキストと現在のコンテキストのキャプチャの詳細については、「 タスク ベースの非同期パターンの使用」を参照してください。 非同期ストリームの詳細については、非同期ストリームの チュートリアルを参照してください。

反復変数の型

次のコードに示すように、 var キーワード を使用して、コンパイラが foreach ステートメント内の反復変数の型を推論できるようにします。

foreach (var item in collection) { }

コンパイラは、null 許容対応コンテキストが有効かどうか、および初期化式の型が参照型かどうかに応じて、 var 宣言の型を 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# 言語仕様」の次のセクションを参照してください。

こちらも参照ください