反復ステートメント - for
、foreach
、do
、while
反復ステートメントは、1 つのステートメントまたはステートメントのブロックを繰り返し実行します。 for
ステートメントでは、指定したブール式が true
と評価される間、その本体を実行します。 foreach
ステートメントでは、コレクションの要素を列挙し、コレクションの各要素に対してその本体を実行します。 do
ステートメントでは、条件に応じてその本体を 1 回または複数回実行します。 while
ステートメントでは、条件に応じてその本体を 0 回または 1 回以上実行します。
反復ステートメントの本文内では、任意の位置に 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
と評価された場合、または存在しない場合は、次の反復が実行され、それ以外の場合はループが終了します。 "条件" セクションは、ブール式にする必要があります。前の例の "条件" セクションでは、カウンターの値が 3 未満かどうかチェックされています。
i < 3
ループの本体の実行が終わるたびに行われる処理が定義されている "反復子" セクション。
前の例の "反復子" セクションでは、カウンターがインクリメントされます。
i++
ループの本体。ステートメントまたはステートメントのブロックである必要があります。
反復子セクションには、次のステートメント式を 0 個以上、コンマで区切って含めることができます。
- 前置または後置のインクリメント式 (
++i
、i++
など) - 前置または後置のデクリメント式 (
--i
、i--
など) - 代入
- メソッドの呼び出し
await
式new
演算子を使用したオブジェクト作成
初期化子セクションでループ変数を宣言しない場合、初期化子セクションの前の一覧にある 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
と、戻り値の型がbool
であるパラメーターなしのパブリック メソッドMoveNext
がある。
次の例では、何のインターフェイスも実装していない System.Span<T> 型のインスタンスを使用して、foreach
ステートメントを使用します。
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) { }
Note
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 回か 1 回以上実行される 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# 言語仕様」の次のセクションを参照してください。
これらの機能の詳細については、機能の提案に関する次の記述を参照してください。
関連項目
.NET