C#のループ処理を完全理解:for・foreach・whileの使い分けと初心者がつまずく注意点

はじめに

C#でプログラムを書くとき、同じ処理を何度も実行したい場面は非常に多くあります。たとえば、配列に入っているデータを順番に表示したり、ユーザーが正しい値を入力するまで入力を求め続けたり、リストの中から条件に合う要素を探したりする場合です。

このような繰り返し処理を実現する仕組みが「ループ」です。C#のループ処理には、主にfor文、foreach文、while文、do-while文があります。

それぞれ似ているように見えますが、得意な場面や注意点が異なります。初心者のうちは「forとforeachの違いがわからない」「whileで無限ループになってしまう」「foreach中にListを削除したらエラーになった」といった悩みがよく起こります。

この記事では、C#のループ処理を初心者にもわかりやすく解説します。基本構文から使い分け、よくあるエラー、実践的なサンプルコードまで順番に確認していきましょう。

1. C#のループ処理とは?繰り返し処理の基本を初心者向けに解説

C#のループ処理とは、同じ処理を条件に応じて何度も実行するための仕組みです。

たとえば、次のように「1から5まで表示する処理」を考えてみます。

C#
Console.WriteLine(1);
Console.WriteLine(2);
Console.WriteLine(3);
Console.WriteLine(4);
Console.WriteLine(5);

このように書いても動きますが、表示する数が100個、1000個になったら大変です。そこでループを使うと、次のように短く書けます。

C#
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}

このコードは、iの値を1から5まで変化させながら、同じConsole.WriteLine(i);を繰り返し実行します。

C#のループを理解すると、配列、List、Dictionary、ユーザー入力、ファイル処理など、さまざまな場面で効率よくコードを書けるようになります。

1-1. ループ処理が必要になる場面

ループ処理は、同じような処理を複数回実行したいときに使います。

代表的な場面は次のとおりです。

C#
string[] names = { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
Console.WriteLine(name);
}

この例では、配列namesに入っている名前を1つずつ取り出して表示しています。

ループ処理が必要になる場面としては、次のようなものがあります。

場面
決まった回数だけ処理する10回メッセージを表示する
配列やListの全要素を処理する商品一覧を表示する
条件を満たすまで繰り返す正しい入力があるまで待つ
データを検索するListの中から特定の値を探す
集計する点数の合計や平均を求める

プログラムでは、データが1件だけとは限りません。複数のデータをまとめて処理するために、C#のループは非常に重要です。

1-2. C#で使える代表的なループの種類

C#でよく使うループ処理には、次の4種類があります。

ループ特徴
for回数やインデックスを管理しながら繰り返す
foreach配列やListなどの要素を順番に取り出す
while条件がtrueの間、繰り返す
do-while最低1回実行してから条件を判定する

それぞれの基本的なイメージは次のとおりです。

C#
// for文
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}

// foreach文
foreach (string item in items)
{
Console.WriteLine(item);
}

// while文
while (condition)
{
// 条件がtrueの間、実行される
}

// do-while文
do
{
// 最低1回は実行される
} while (condition);

C#のループ処理では、「何を基準に繰り返すのか」を考えることが大切です。回数なのか、コレクションの要素なのか、条件なのかによって、使う構文を選びます。

1-3. for・foreach・while・do-whileの違いを一覧で比較

C#のループの違いを一覧で整理すると、次のようになります。

種類主な用途特徴向いているケース
for回数指定、インデックス操作初期化・条件・増減をまとめて書ける10回繰り返す、配列の添字を使う
foreachコレクション処理要素を1つずつ取り出せる配列やListを順番に処理する
while条件ベースの繰り返し条件がtrueの間だけ実行入力待ち、条件達成まで処理
do-while最低1回実行する処理実行後に条件判定するメニュー表示、入力チェック

初心者のうちは、次のように覚えるとわかりやすいです。

C#
// 回数が決まっている
for

// 配列やListを全部処理する
foreach

// 条件が満たされるまで繰り返す
while

// 最低1回は実行したい
do-while

実務ではforforeachの使用頻度が高く、次にwhile、必要に応じてdo-whileを使うことが多いです。

2. for文の基本構文と使い方

for文は、C#のループ処理の中でも特によく使われる構文です。繰り返す回数が決まっている場合や、配列・Listのインデックスを使いたい場合に便利です。

たとえば、1から5まで表示する場合は次のように書きます。

C#
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}

実行結果は次のようになります。

1
2
3
4
5

for文では、カウンター変数を使って「何回目の繰り返しか」を管理します。

2-1. for文の書き方

for文の基本構文は次のとおりです。

C#
for (初期化; 条件式; 増減式)
{
// 繰り返したい処理
}

具体例を見てみましょう。

C#
for (int i = 0; i < 3; i++)
{
Console.WriteLine("こんにちは");
}

このコードでは、Console.WriteLine("こんにちは");が3回実行されます。

処理の流れは次のようになります。

  1. int i = 0でカウンター変数を初期化する

  2. i < 3がtrueか確認する

  3. trueならブロック内の処理を実行する

  4. i++iを1増やす

  5. 再び条件式を確認する

  6. 条件式がfalseになったらループ終了

for文は、初期化、条件式、増減式が1行にまとまっているため、繰り返し回数を管理しやすいのが特徴です。

2-2. カウンター変数・条件式・増減式の意味

次のコードを例に、for文の各部分を詳しく見てみましょう。

C#
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
部分意味
int i = 0カウンター変数iを0で開始する
i < 5iが5未満の間だけ繰り返す
i++1回処理するたびにiを1増やす

i++は、i = i + 1と同じ意味です。

C#
i++;

カウンター変数名はiである必要はありませんが、短いループでは慣習的にiがよく使われます。二重ループではijkのように使い分けることもあります。

C#
for (int row = 0; row < 3; row++)
{
for (int column = 0; column < 3; column++)
{
Console.WriteLine($"row: {row}, column: {column}");
}
}

読みやすさを重視する場合は、rowindexのように意味のある名前を使うとよいでしょう。

2-3. 配列やListをfor文で処理する例

for文は、配列やListの要素をインデックスで処理したいときによく使います。

配列を処理する例です。

C#
string[] fruits = { "りんご", "みかん", "バナナ" };

for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine(fruits[i]);
}

配列の要素数はLengthプロパティで取得できます。

Listを処理する場合は、Countプロパティを使います。

C#
List<string> fruits = new List<string> { "りんご", "みかん", "バナナ" };

for (int i = 0; i < fruits.Count; i++)
{
Console.WriteLine(fruits[i]);
}

インデックスも一緒に表示したい場合は、for文が便利です。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i + 1}番目: {names[i]}");
}

実行結果は次のようになります。

1番目: 田中
2番目: 佐藤
3番目: 鈴木

このように、要素の位置を使いたい場合はforeachよりfor文の方が扱いやすいです。

2-4. for文が向いているケース

for文が向いているのは、主に次のようなケースです。

ケース理由
繰り返し回数が決まっているカウンターで回数を管理しやすい
インデックスが必要array[i]list[i]のようにアクセスできる
逆順に処理したいi--で後ろから処理できる
一部の範囲だけ処理したい開始位置と終了条件を自由に指定できる

たとえば、Listを後ろから表示する場合は次のように書けます。

C#
List<string> items = new List<string> { "A", "B", "C" };

for (int i = items.Count - 1; i >= 0; i--)
{
Console.WriteLine(items[i]);
}

実行結果は次のとおりです。

C
B
A

また、偶数番目だけ処理したい場合にもfor文は便利です。

C#
for (int i = 0; i < items.Count; i += 2)
{
Console.WriteLine(items[i]);
}

このように、繰り返しの開始位置、終了条件、増え方を細かく制御したいときはfor文を使うとよいでしょう。

2-5. for文で初心者がつまずきやすい注意点

for文で初心者がよくつまずくのは、条件式とインデックスの扱いです。

特に多いのが、配列の範囲外にアクセスしてしまうエラーです。

C#
int[] numbers = { 10, 20, 30 };

for (int i = 0; i <= numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}

このコードはエラーになります。

配列のインデックスは0から始まるため、要素数が3の場合、使えるインデックスは012です。numbers.Lengthは3なので、i <= numbers.Lengthにするとnumbers[3]へアクセスしてしまいます。

正しくは次のように書きます。

C#
int[] numbers = { 10, 20, 30 };

for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}

また、増減式を書き忘れると無限ループになることがあります。

C#
for (int i = 0; i < 5;)
{
Console.WriteLine(i);
}

この場合、iがずっと0のままなので、i < 5が常にtrueになってしまいます。

for文では、次の3点を必ず確認しましょう。

確認項目ポイント
初期値どこから始めるか
条件式いつ終了するか
増減式ループごとに値が変化するか

3. foreach文の基本構文と使い方

foreach文は、配列やList、Dictionaryなどのコレクションから要素を1つずつ取り出して処理するためのループです。

for文のようにインデックスを意識する必要がないため、コードが読みやすくなります。

C#
string[] fruits = { "りんご", "みかん", "バナナ" };

foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}

このコードでは、fruitsの中から要素を1つずつ取り出し、fruitという変数に入れて処理しています。

実行結果は次のとおりです。

りんご
みかん
バナナ

3-1. foreach文の書き方

foreach文の基本構文は次のとおりです。

C#
foreach ( 変数名 in コレクション)
{
// 繰り返したい処理
}

たとえば、整数の配列を処理する場合は次のように書きます。

C#
int[] numbers = { 10, 20, 30 };

foreach (int number in numbers)
{
Console.WriteLine(number);
}

foreach文では、コレクションの要素が順番に変数へ代入されます。

この例では、1回目のループでnumber10、2回目で20、3回目で30が入ります。

foreachは、コレクションの全要素を順番に処理したいときに非常に便利です。

3-2. 配列・List・Dictionaryをforeachで処理する例

配列をforeachで処理する例です。

C#
string[] colors = { "赤", "青", "緑" };

foreach (string color in colors)
{
Console.WriteLine(color);
}

Listを処理する場合も同じように書けます。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
Console.WriteLine(name);
}

Dictionaryを処理する場合は、キーと値を取り出せます。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

foreach (KeyValuePair<string, int> score in scores)
{
Console.WriteLine($"{score.Key}: {score.Value}点");
}

また、型推論を使ってvarで書くこともできます。

C#
foreach (var score in scores)
{
Console.WriteLine($"{score.Key}: {score.Value}点");
}

Dictionaryでは、score.Keyでキー、score.Valueで値を取得します。

3-3. foreach文が向いているケース

foreach文が向いているのは、コレクションの全要素を順番に処理したい場合です。

たとえば、次のような場面で使います。

ケース
配列の全要素を表示する商品名を一覧表示する
Listの全要素をチェックするユーザー一覧を処理する
Dictionaryのキーと値を表示する名前と点数を表示する
インデックスが不要要素そのものだけ使う

たとえば、商品の一覧を表示するだけならforeachが読みやすいです。

C#
List<string> products = new List<string> { "ノートPC", "マウス", "キーボード" };

foreach (string product in products)
{
Console.WriteLine(product);
}

このコードでは、インデックス番号を使う必要がありません。そのため、for文よりもシンプルに書けます。

C#
for (int i = 0; i < products.Count; i++)
{
Console.WriteLine(products[i]);
}

どちらも同じ結果になりますが、要素を順番に取り出すだけならforeachの方が意図が伝わりやすいです。

3-4. foreach内で要素を変更・削除するときの注意点

foreach文では、ループ中にコレクション自体を変更するとエラーになることがあります。

たとえば、次のコードは問題があります。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
if (name == "佐藤")
{
names.Remove(name);
}
}

このようにforeachでListを回している最中にRemoveすると、コレクションが変更されたためエラーになる可能性があります。

削除したい場合は、for文で後ろから処理する方法があります。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

for (int i = names.Count - 1; i >= 0; i--)
{
if (names[i] == "佐藤")
{
names.RemoveAt(i);
}
}

後ろから削除することで、インデックスのずれを防げます。

また、条件に合う要素をまとめて削除したい場合は、RemoveAllを使うと簡潔です。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

names.RemoveAll(name => name == "佐藤");

foreachは読みやすい反面、ループ中の追加・削除には注意が必要です。

3-5. for文とforeach文の使い分け

for文とforeach文の使い分けは、C#のループ処理で特に迷いやすいポイントです。

基本的には、次のように考えるとよいでしょう。

使いたいことおすすめ
要素を順番に処理するだけforeach
インデックスが必要for
逆順に処理したいfor
要素を削除したいforまたは専用メソッド
全要素を読み取るだけforeach

たとえば、単純に表示するだけならforeachです。

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

一方、番号付きで表示したい場合はforが便利です。

C#
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i + 1}: {names[i]}");
}

C#のループでは、「インデックスが必要かどうか」を基準に考えると選びやすくなります。

4. while文の基本構文と使い方

while文は、条件式がtrueの間だけ処理を繰り返すループです。

for文のように回数が明確に決まっている場合よりも、「条件を満たすまで続けたい」という場面に向いています。

基本的な例を見てみましょう。

C#
int count = 0;

while (count < 3)
{
Console.WriteLine(count);
count++;
}

実行結果は次のとおりです。

0
1
2

count < 3がtrueの間、ブロック内の処理が繰り返されます。

4-1. while文の書き方

while文の基本構文は次のとおりです。

C#
while (条件式)
{
// 条件式がtrueの間、繰り返す処理
}

条件式が最初に判定され、trueであれば処理が実行されます。falseであれば、1回も実行されません。

C#
int number = 10;

while (number < 5)
{
Console.WriteLine(number);
}

このコードでは、最初からnumber < 5がfalseなので、ループ内の処理は一度も実行されません。

while文は、条件が成立している間だけ処理したいときに使います。

4-2. 条件がtrueの間だけ処理を繰り返す仕組み

while文では、ループのたびに条件式を確認します。

C#
int count = 1;

while (count <= 5)
{
Console.WriteLine(count);
count++;
}

このコードの流れは次のようになります。

回数countの値条件 count <= 5処理
1回目1true表示してcountを増やす
2回目2true表示してcountを増やす
3回目3true表示してcountを増やす
4回目4true表示してcountを増やす
5回目5true表示してcountを増やす
6回目6false終了

while文では、条件をfalseに近づける処理が重要です。

この例では、count++があるため、いつかcount <= 5がfalseになります。もしcount++を書き忘れると、条件がずっとtrueになり、無限ループになります。

4-3. ユーザー入力や条件待ちで使う例

while文は、ユーザーが正しい値を入力するまで繰り返す処理によく使われます。

C#
string input = "";

while (input != "exit")
{
Console.Write("コマンドを入力してください: ");
input = Console.ReadLine();

Console.WriteLine($"入力値: {input}");
}

このコードでは、ユーザーがexitと入力するまで処理を繰り返します。

数値入力をチェックする例も見てみましょう。

C#
int number;

Console.Write("数値を入力してください: ");

while (!int.TryParse(Console.ReadLine(), out number))
{
Console.Write("数値ではありません。もう一度入力してください: ");
}

Console.WriteLine($"入力された数値: {number}");

int.TryParseは、文字列を数値に変換できるかどうかを判定します。変換できなかった場合はfalseになるため、再入力を求めます。

このように、繰り返し回数が事前にわからない場合はwhile文が便利です。

4-4. while文が向いているケース

while文が向いているのは、繰り返し回数ではなく条件を基準に処理したい場合です。

ケース
正しい入力まで繰り返す数値が入力されるまで待つ
特定の状態になるまで待つ処理が完了するまで監視する
条件を満たす間だけ処理する残高がある間、購入処理をする
終了コマンドまで続けるexitが入力されるまで実行する

たとえば、残高がある間だけ処理する例です。

C#
int balance = 500;

while (balance > 0)
{
Console.WriteLine($"現在の残高: {balance}");
balance -= 100;
}

while文は柔軟ですが、終了条件を正しく設計しないと無限ループになりやすいため注意が必要です。

4-5. 無限ループを防ぐための注意点

while文で最も注意したいのが無限ループです。

無限ループとは、条件式がずっとtrueのままになり、ループが終わらない状態です。

C#
int count = 0;

while (count < 5)
{
Console.WriteLine(count);
}

このコードでは、countが増えないため、count < 5がずっとtrueになります。

正しくは次のように、ループ内でcountを変化させます。

C#
int count = 0;

while (count < 5)
{
Console.WriteLine(count);
count++;
}

また、あえて無限ループを書いて、内部でbreakするケースもあります。

C#
while (true)
{
Console.Write("終了するにはexitと入力してください: ");
string input = Console.ReadLine();

if (input == "exit")
{
break;
}
}

このような書き方は実務でも使われますが、必ず終了条件を用意しましょう。

5. do-while文の基本構文と使い方

do-while文は、処理を実行したあとに条件式を判定するループです。

通常のwhile文は、最初に条件式を判定します。一方、do-while文は先に処理を実行するため、条件に関係なく最低1回は処理されます。

C#
int count = 0;

do
{
Console.WriteLine(count);
count++;
} while (count < 3);

実行結果は次のとおりです。

0
1
2

do-while文は、メニュー表示や入力チェックなど、「まず1回は実行したい処理」に向いています。

5-1. do-while文の書き方

do-while文の基本構文は次のとおりです。

C#
do
{
// 繰り返したい処理
} while (条件式);

最後のwhile (条件式);の末尾にはセミコロンが必要です。

具体例を見てみましょう。

C#
int number = 1;

do
{
Console.WriteLine(number);
number++;
} while (number <= 5);

このコードでは、numberが1から5まで表示されます。

do-while文は、先に処理を行い、その後で「もう一度繰り返すか」を判断する構文です。

5-2. while文との違い

while文とdo-while文の最大の違いは、条件式を判定するタイミングです。

種類条件判定のタイミング最低実行回数
while処理の前0回
do-while処理の後1回

次のwhile文は、条件が最初からfalseなので実行されません。

C#
int number = 10;

while (number < 5)
{
Console.WriteLine(number);
}

一方、do-while文は条件がfalseでも1回は実行されます。

C#
int number = 10;

do
{
Console.WriteLine(number);
} while (number < 5);

このコードでは、number < 5はfalseですが、先に処理されるため10が表示されます。

5-3. 最低1回は処理したい場合の使用例

do-while文は、ユーザー入力を最低1回は受け取りたい場合に便利です。

C#
string input;

do
{
Console.Write("パスワードを入力してください: ");
input = Console.ReadLine();
} while (input != "secret");

Console.WriteLine("ログイン成功");

このコードでは、最初に必ずパスワード入力を求めます。その後、入力値がsecretでなければ再入力を求めます。

メニュー処理にも向いています。

C#
int menu;

do
{
Console.WriteLine("1: 開始");
Console.WriteLine("2: 設定");
Console.WriteLine("0: 終了");
Console.Write("番号を選択してください: ");

int.TryParse(Console.ReadLine(), out menu);

} while (menu != 0);

Console.WriteLine("終了しました");

メニューは最初に必ず表示する必要があるため、do-while文と相性がよいです。

5-4. do-while文を使うべき場面

do-while文を使うべき場面は、「条件判定よりも先に、まず処理を1回実行したい」ときです。

場面理由
メニュー表示最初に選択肢を表示する必要がある
入力チェックまず入力してもらう必要がある
リトライ処理最初の処理を試してから継続判断する
ゲームループ最低1回は画面更新や入力処理を行う

ただし、実務ではwhile文で同じ処理を書ける場合も多いため、無理にdo-while文を使う必要はありません。

「最低1回は必ず実行される」という特徴がコードの意図に合う場合に使うとよいでしょう。

5-5. do-while文で注意すべき条件式の書き方

do-while文では、条件式の意味を間違えると、意図しないループになることがあります。

たとえば、「0が入力されるまで繰り返す」場合は、条件式を次のように書きます。

C#
do
{
Console.Write("数値を入力してください。0で終了: ");
int.TryParse(Console.ReadLine(), out number);
} while (number != 0);

number != 0は、「numberが0ではない間、繰り返す」という意味です。

初心者が間違えやすいのは、終了条件をそのまま書いてしまうことです。

C#
// 間違いやすい例
do
{
Console.Write("数値を入力してください。0で終了: ");
int.TryParse(Console.ReadLine(), out number);
} while (number == 0);

この場合、「0の間だけ繰り返す」という意味になってしまい、意図と逆になります。

ループ条件は「続ける条件」を書くのが基本です。終了したい条件ではなく、継続したい条件を書く点に注意しましょう。

6. ループ制御で使うbreak・continue・return

C#のループ処理では、breakcontinuereturnを使ってループの流れを制御できます。

これらは似ているように見えますが、動きが異なります。

キーワード動き
breakループを終了する
continue現在の回をスキップして次の繰り返しへ進む
returnメソッド自体を終了する

ループを途中で抜けたいときや、特定の条件だけ処理を飛ばしたいときに使います。

6-1. breakでループを終了する

breakは、ループを途中で終了するために使います。

C#
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break;
}

Console.WriteLine(i);
}

実行結果は次のとおりです。

0
1
2
3
4

i == 5になった時点でbreakが実行され、for文全体が終了します。

Listの中から特定の要素を探す場合にも使えます。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
if (name == "佐藤")
{
Console.WriteLine("佐藤さんが見つかりました");
break;
}
}

目的の要素が見つかったら、それ以上ループする必要がないためbreakで終了します。

6-2. continueで次の繰り返しに進む

continueは、現在の繰り返し処理を途中でスキップし、次の繰り返しへ進むために使います。

C#
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
continue;
}

Console.WriteLine(i);
}

実行結果は次のとおりです。

1
2
4
5

i == 3のときはcontinueが実行されるため、Console.WriteLine(i);は実行されません。

偶数だけ表示する例も見てみましょう。

C#
for (int i = 1; i <= 10; i++)
{
if (i % 2 != 0)
{
continue;
}

Console.WriteLine(i);
}

このコードでは、奇数の場合はスキップし、偶数だけ表示します。

6-3. returnでメソッドごと終了する

returnは、ループだけでなく、メソッド自体を終了します。

C#
static void FindName(List<string> names)
{
foreach (string name in names)
{
if (name == "佐藤")
{
Console.WriteLine("佐藤さんが見つかりました");
return;
}
}

Console.WriteLine("見つかりませんでした");
}

この例では、佐藤が見つかった時点でreturnが実行され、FindNameメソッドが終了します。

そのため、後ろにあるConsole.WriteLine("見つかりませんでした");は実行されません。

値を返すメソッドでもreturnはよく使います。

C#
static bool ContainsName(List<string> names, string target)
{
foreach (string name in names)
{
if (name == target)
{
return true;
}
}

return false;
}

このように、条件に合う値が見つかったらすぐに結果を返すことで、無駄なループを減らせます。

6-4. break・continue・returnの違い

breakcontinuereturnの違いを整理すると次のようになります。

キーワード終了する範囲主な用途
breakループ条件を満たしたらループを抜ける
continue今回の処理だけ特定の回だけスキップする
returnメソッド結果を返して処理を終える

違いをコードで確認してみましょう。

C#
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
break;
}

Console.WriteLine(i);
}

この場合は3になった時点でループ終了です。

C#
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
continue;
}

Console.WriteLine(i);
}

この場合は3だけスキップされます。

C#
static void Test()
{
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
return;
}

Console.WriteLine(i);
}

Console.WriteLine("ループ終了");
}

この場合は3になった時点でメソッド自体が終了するため、ループ終了も表示されません。

6-5. ネストしたループで使うときの注意点

ネストしたループとは、ループの中にさらにループがある状態です。

C#
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.WriteLine($"{i}, {j}");
}
}

ネストしたループでbreakを使うと、内側のループだけが終了します。

C#
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (j == 1)
{
break;
}

Console.WriteLine($"{i}, {j}");
}
}

この場合、breakで終了するのは内側のfor (int j = 0; j < 3; j++)だけです。外側のループは続きます。

外側のループも含めて終了したい場合は、フラグ変数を使う方法があります。

C#
bool found = false;

for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i == 1 && j == 1)
{
found = true;
break;
}
}

if (found)
{
break;
}
}

また、メソッド内であればreturnを使って一気に終了する方法もあります。

C#
static void Search()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i == 1 && j == 1)
{
return;
}
}
}
}

ネストが深いと処理の流れが読みにくくなるため、必要に応じてメソッドに分けることも大切です。

7. for・foreach・whileの使い分け早見表

C#のループ処理では、目的に合わせて適切な構文を選ぶことが重要です。

使い分けの目安は次のとおりです。

やりたいことおすすめのループ
決まった回数だけ繰り返すfor
配列やListを順番に処理するforeach
条件を満たすまで繰り返すwhile
最低1回は実行するdo-while
インデックスを使うfor
コレクションを読み取るだけforeach
入力チェックをするwhileまたはdo-while

迷ったときは、「回数」「要素」「条件」「最低1回」のどれを基準にするかを考えると選びやすくなります。

7-1. 回数が決まっているならfor文

繰り返し回数が決まっている場合は、for文が適しています。

C#
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"{i + 1}回目の処理");
}

このコードは10回だけ処理を実行します。

for文は、開始値、終了条件、増減式が1か所にまとまっているため、何回繰り返すのかがわかりやすいです。

配列のインデックスを使いたい場合にも向いています。

C#
int[] scores = { 80, 90, 75 };

for (int i = 0; i < scores.Length; i++)
{
Console.WriteLine($"{i + 1}人目の点数: {scores[i]}");
}

回数や順番を明確に管理したい場合は、for文を選びましょう。

7-2. コレクションの全要素を処理するならforeach文

配列、List、Dictionaryなどの全要素を順番に処理したい場合は、foreach文が適しています。

C#
List<string> users = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string user in users)
{
Console.WriteLine(user);
}

foreach文は、インデックスを使わずに要素そのものを取り出せるため、コードがシンプルになります。

Dictionaryの場合も、キーと値をわかりやすく処理できます。

C#
Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "田中", 25 },
{ "佐藤", 30 }
};

foreach (var age in ages)
{
Console.WriteLine($"{age.Key}さんは{age.Value}歳です");
}

全要素を読み取るだけなら、まずforeachを検討するとよいでしょう。

7-3. 条件を満たすまで繰り返すならwhile文

繰り返し回数が事前に決まっていない場合は、while文が適しています。

C#
string input = "";

while (input != "yes")
{
Console.Write("yesと入力してください: ");
input = Console.ReadLine();
}

このコードでは、ユーザーがyesと入力するまで処理を繰り返します。

while文は、次のような条件ベースの処理に向いています。

C#
while (!isCompleted)
{
// 完了するまで処理を続ける
}

ただし、条件がいつfalseになるのかを明確にしておかないと、無限ループになる可能性があります。

7-4. 最低1回実行したいならdo-while文

処理を最低1回は実行したい場合は、do-while文が適しています。

C#
string input;

do
{
Console.Write("終了するにはexitと入力してください: ");
input = Console.ReadLine();
} while (input != "exit");

このコードでは、最初に必ず入力を求めます。

do-while文は、入力処理やメニュー表示のように、最初の1回が必ず必要な処理で使いやすいです。

C#
int choice;

do
{
Console.WriteLine("1: 実行");
Console.WriteLine("0: 終了");
int.TryParse(Console.ReadLine(), out choice);
} while (choice != 0);

「先に実行してから、続けるかどうかを判断する」と考えると理解しやすいです。

7-5. 実務で迷いやすいケース別の選び方

実務では、次のような判断でループを選ぶと読みやすいコードになります。

ケース選び方
Listの全件を表示するforeach
Listの一部を削除する後ろからfor、またはRemoveAll
配列のインデックスも表示するfor
条件に合う要素を1つ探すforeach + break、またはLINQ
入力値が正しいまで繰り返すwhileまたはdo-while
決まった回数リトライするfor
成功するまでリトライするwhile

たとえば、条件に合うユーザーを探すだけならforeachで十分です。

C#
foreach (var user in users)
{
if (user.Name == "田中")
{
Console.WriteLine("見つかりました");
break;
}
}

一方、最大3回までリトライするならfor文が適しています。

C#
for (int retryCount = 0; retryCount < 3; retryCount++)
{
Console.WriteLine("処理を試行します");
}

C#のループ処理では、動くことだけでなく、後から読んだ人が意図を理解しやすい構文を選ぶことが大切です。

8. 初心者がつまずくC#ループ処理の注意点

C#のループは便利ですが、初心者がつまずきやすいポイントも多くあります。

特に注意したいのは次の5つです。

注意点起こる問題
条件式の書き間違いループしない、終わらない
インデックス範囲外実行時エラーになる
無限ループプログラムが止まらない
foreach中のコレクション変更例外が発生する
ネストが深すぎる読みにくくなる

それぞれ詳しく確認していきましょう。

8-1. 条件式の書き間違い

条件式の書き間違いは、ループ処理でよくあるミスです。

たとえば、1から5まで表示したい場合に、次のように書くと意図した結果になりません。

C#
for (int i = 1; i < 5; i++)
{
Console.WriteLine(i);
}

このコードでは、表示されるのは1から4までです。5も表示したい場合は、i <= 5にする必要があります。

C#
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}

条件式では、<<=>>=の違いを意識しましょう。

また、比較演算子と代入演算子の違いにも注意が必要です。

C#
// 比較
if (count == 5)
{
}

// 代入
count = 5;

C#では、条件式にcount = 5のような代入を書くとコンパイルエラーになるケースが多いですが、条件の意味を取り違えないよう注意しましょう。

8-2. インデックス範囲外エラー

配列やListをfor文で処理するときに多いのが、インデックス範囲外エラーです。

C#
int[] numbers = { 10, 20, 30 };

for (int i = 0; i <= numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}

配列の最後のインデックスはLength - 1です。上のコードでは、最後にnumbers[3]へアクセスしようとしてエラーになります。

正しくは次のように書きます。

C#
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}

Listの場合も同じです。

C#
List<int> numbers = new List<int> { 10, 20, 30 };

for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine(numbers[i]);
}

C#の配列やListのインデックスは0から始まることを必ず覚えておきましょう。

8-3. 無限ループ

無限ループは、条件式がずっとtrueになり、ループが終わらない状態です。

C#
int count = 0;

while (count < 10)
{
Console.WriteLine(count);
}

このコードでは、countが変化しないため、ずっとcount < 10がtrueです。

正しくは、ループ内でcountを増やします。

C#
int count = 0;

while (count < 10)
{
Console.WriteLine(count);
count++;
}

また、for文でも条件式を間違えると無限ループになります。

C#
for (int i = 0; i >= 0; i++)
{
Console.WriteLine(i);
}

iは増え続けるため、i >= 0が長い間trueになり続けます。

無限ループを防ぐには、次の点を確認しましょう。

確認項目内容
条件式いつfalseになるか
変数の更新ループ内で値が変わるか
break条件必要に応じて終了条件があるか

8-4. foreach中のコレクション変更エラー

foreachでコレクションを処理している最中に、そのコレクションを追加・削除するとエラーになることがあります。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
if (number % 2 == 0)
{
numbers.Remove(number);
}
}

このような書き方は避けましょう。

削除したい場合は、RemoveAllを使うと安全です。

C#
numbers.RemoveAll(number => number % 2 == 0);

または、for文で後ろから削除します。

C#
for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}

foreachは読み取り中心の処理に使い、コレクションの変更が必要な場合は別の方法を選ぶのが基本です。

8-5. ネストが深すぎて読みにくくなる問題

ループの中にループを入れることをネストといいます。

C#
foreach (var order in orders)
{
foreach (var item in order.Items)
{
foreach (var option in item.Options)
{
Console.WriteLine(option.Name);
}
}
}

ネストが深くなると、どの処理がどのループに属しているのかわかりにくくなります。

読みやすくするには、処理をメソッドに分ける方法があります。

C#
foreach (var order in orders)
{
PrintOrderOptions(order);
}

static void PrintOrderOptions(Order order)
{
foreach (var item in order.Items)
{
foreach (var option in item.Options)
{
Console.WriteLine(option.Name);
}
}
}

また、条件分岐が深くなる場合は、早めにcontinueを使って処理をスキップする方法もあります。

C#
foreach (var user in users)
{
if (!user.IsActive)
{
continue;
}

Console.WriteLine(user.Name);
}

ネストを減らすと、C#のループ処理はかなり読みやすくなります。

9. 実践例で理解するC#のループ処理

ここからは、C#のループ処理を実践例で確認していきます。

基本的な表示、合計値の計算、条件検索、入力チェック、Dictionaryの処理など、よく使うパターンを紹介します。

9-1. 1から10まで表示する

1から10まで表示する場合は、for文を使うと簡単です。

C#
for (int i = 1; i <= 10; i++)
{
Console.WriteLine(i);
}

実行結果は次のとおりです。

1
2
3
4
5
6
7
8
9
10

iを1から始め、i <= 10の間だけ繰り返しています。

0から始めたい場合は次のように書きます。

C#
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}

C#では配列やListのインデックスが0から始まるため、プログラムでは0始まりのループもよく使われます。

9-2. 配列の合計値を求める

配列に入っている数値の合計を求める例です。

C#
int[] numbers = { 10, 20, 30, 40 };

int total = 0;

foreach (int number in numbers)
{
total += number;
}

Console.WriteLine($"合計: {total}");

実行結果は次のとおりです。

合計: 100

total += number;は、total = total + number;と同じ意味です。

インデックスが不要なため、この場合はforeachが読みやすいです。

for文で書くこともできます。

C#
int total = 0;

for (int i = 0; i < numbers.Length; i++)
{
total += numbers[i];
}

Console.WriteLine($"合計: {total}");

要素を順番に取り出すだけならforeach、インデックスが必要ならforを使いましょう。

9-3. Listの中から条件に合う要素を探す

Listの中から特定の名前を探す例です。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
if (name == "佐藤")
{
Console.WriteLine("佐藤さんが見つかりました");
break;
}
}

条件に合う要素が見つかったら、breakでループを終了しています。

見つかったかどうかを後で使いたい場合は、フラグ変数を使います。

C#
bool found = false;

foreach (string name in names)
{
if (name == "佐藤")
{
found = true;
break;
}
}

if (found)
{
Console.WriteLine("見つかりました");
}
else
{
Console.WriteLine("見つかりませんでした");
}

実務では、LINQのAnyFirstOrDefaultを使うこともあります。

C#
bool exists = names.Any(name => name == "佐藤");

Console.WriteLine(exists ? "見つかりました" : "見つかりませんでした");

初心者のうちは、まずforeachで処理の流れを理解してからLINQを覚えるとよいでしょう。

9-4. 入力値が正しいまで繰り返す

ユーザーが正しい数値を入力するまで繰り返す例です。

C#
int age;

Console.Write("年齢を入力してください: ");

while (!int.TryParse(Console.ReadLine(), out age))
{
Console.Write("数値で入力してください: ");
}

Console.WriteLine($"入力された年齢: {age}");

int.TryParseは、入力された文字列を整数に変換できるか確認します。

変換できない場合はfalseになるため、while文で再入力を求めます。

さらに、1以上の数値だけを許可したい場合は次のように書けます。

C#
int age;

while (true)
{
Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();

if (int.TryParse(input, out age) && age >= 1)
{
break;
}

Console.WriteLine("1以上の数値を入力してください。");
}

Console.WriteLine($"入力された年齢: {age}");

このように、回数が決まっていない入力チェックにはwhile文が向いています。

9-5. Dictionaryのキーと値を取り出す

Dictionaryのキーと値を取り出すには、foreach文を使います。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 95 },
{ "鈴木", 70 }
};

foreach (var score in scores)
{
Console.WriteLine($"{score.Key}: {score.Value}点");
}

実行結果は次のとおりです。

田中: 80点
佐藤: 95点
鈴木: 70点

キーだけを取り出したい場合は、Keysを使います。

C#
foreach (string name in scores.Keys)
{
Console.WriteLine(name);
}

値だけを取り出したい場合は、Valuesを使います。

C#
foreach (int point in scores.Values)
{
Console.WriteLine(point);
}

Dictionaryを使うと、名前と点数、商品コードと商品名など、キーと値の組み合わせを効率よく扱えます。

10. C#のループ処理を読みやすく書くコツ

C#のループ処理は、正しく動くだけでなく、読みやすく書くことも大切です。

特に実務では、自分以外の人がコードを読むことも多いため、意図が伝わる書き方を意識しましょう。

読みやすくするポイントは次のとおりです。

コツ内容
変数名をわかりやすくするxよりuserindexなど
条件式をシンプルにする複雑な条件は変数に分ける
ネストを減らすメソッド化やcontinueを使う
LINQを使う検索や集計を簡潔に書く
コメントを適切に入れる意図がわかりにくい処理を補足する

10-1. 変数名をわかりやすくする

ループで使う変数名は、処理内容が伝わる名前にしましょう。

悪い例です。

C#
foreach (var x in users)
{
Console.WriteLine(x.Name);
}

xでは何を表しているのかわかりにくいです。

よい例です。

C#
foreach (var user in users)
{
Console.WriteLine(user.Name);
}

userという名前にすることで、ユーザー情報を処理していることがすぐにわかります。

for文のカウンター変数はiでも問題ありませんが、意味がある場合はindexrowなどを使うと読みやすくなります。

C#
for (int index = 0; index < names.Count; index++)
{
Console.WriteLine($"{index + 1}: {names[index]}");
}

変数名は、短さよりも意味のわかりやすさを優先しましょう。

10-2. 条件式をシンプルにする

ループの条件式が複雑すぎると、処理の意図がわかりにくくなります。

C#
while (user != null && user.IsActive && user.LoginCount < 5 && !user.IsLocked)
{
// 処理
}

このように条件が長い場合は、意味のある変数に分けると読みやすくなります。

C#
bool canLogin = user != null
&& user.IsActive
&& user.LoginCount < 5
&& !user.IsLocked;

while (canLogin)
{
// 処理

canLogin = user != null
&& user.IsActive
&& user.LoginCount < 5
&& !user.IsLocked;
}

または、メソッドに分ける方法もあります。

C#
while (CanLogin(user))
{
// 処理
}

static bool CanLogin(User user)
{
return user != null
&& user.IsActive
&& user.LoginCount < 5
&& !user.IsLocked;
}

条件式をシンプルにすると、バグの発見もしやすくなります。

10-3. ネストを減らす

ネストが深いループは読みにくく、修正もしづらくなります。

C#
foreach (var user in users)
{
if (user.IsActive)
{
if (user.Age >= 20)
{
Console.WriteLine(user.Name);
}
}
}

このような場合は、continueを使って早めにスキップすると読みやすくなります。

C#
foreach (var user in users)
{
if (!user.IsActive)
{
continue;
}

if (user.Age < 20)
{
continue;
}

Console.WriteLine(user.Name);
}

条件を反転させて、対象外のデータを先に除外するイメージです。

また、処理が長くなる場合はメソッドに分けましょう。

C#
foreach (var user in users)
{
PrintAdultActiveUser(user);
}

static void PrintAdultActiveUser(User user)
{
if (!user.IsActive)
{
return;
}

if (user.Age < 20)
{
return;
}

Console.WriteLine(user.Name);
}

ネストを減らすことで、C#のループ処理はかなり読みやすくなります。

10-4. 必要に応じてLINQを使う

C#では、ループ処理の代わりにLINQを使うと簡潔に書ける場合があります。

たとえば、Listの中から20歳以上のユーザーだけを取り出す処理を考えます。

C#
List<User> adults = new List<User>();

foreach (var user in users)
{
if (user.Age >= 20)
{
adults.Add(user);
}
}

LINQを使うと次のように書けます。

C#
List<User> adults = users
.Where(user => user.Age >= 20)
.ToList();

合計値を求める場合も、LINQを使うと短く書けます。

C#
int total = scores.Sum();

条件に合う要素が存在するか調べる場合はAnyが使えます。

C#
bool hasAdult = users.Any(user => user.Age >= 20);

ただし、初心者のうちはすべてをLINQで書こうとする必要はありません。まずはforforeachwhileで処理の流れを理解し、その後でLINQを使うと理解しやすくなります。

10-5. コメントを入れるべき場面

コメントは、コードの意図を補足するために使います。

ただし、見ればわかる処理にコメントを入れすぎると、かえって読みにくくなります。

あまりよくない例です。

C#
// iを0から10未満まで1ずつ増やす
for (int i = 0; i < 10; i++)
{
// iを表示する
Console.WriteLine(i);
}

このコメントは、コードを読めばわかる内容です。

一方、処理の理由や業務上のルールはコメントすると役立ちます。

C#
// 退会済みユーザーは通知対象外にする
foreach (var user in users)
{
if (user.IsDeleted)
{
continue;
}

SendNotification(user);
}

コメントを書くべきなのは、「何をしているか」よりも「なぜそうしているか」がわかりにくい場合です。

11. C#ループ処理に関するよくある質問

ここでは、C#のループ処理について初心者がよく疑問に思うポイントをまとめます。

11-1. for文とforeach文はどちらを使うべき?

インデックスが必要な場合はfor文、不要な場合はforeach文を使うのが基本です。

C#
// インデックスが必要
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i + 1}: {names[i]}");
}
C#
// 要素だけ使う
foreach (string name in names)
{
Console.WriteLine(name);
}

コレクションの全要素を読むだけなら、foreachの方がシンプルで読みやすいです。

一方、逆順に処理したい場合や、要素を削除したい場合はfor文が向いています。

11-2. while文とdo-while文の違いは?

while文は、処理の前に条件を判定します。そのため、条件が最初からfalseなら一度も実行されません。

C#
while (condition)
{
// conditionがtrueなら実行
}

do-while文は、処理の後に条件を判定します。そのため、最低1回は実行されます。

C#
do
{
// 最低1回は実行
} while (condition);

入力処理やメニュー表示のように、まず1回実行したい場合はdo-while文が便利です。

11-3. foreachでインデックスを使いたい場合は?

foreach文自体には、標準でインデックス変数はありません。

インデックスが必要な場合は、for文を使うのがわかりやすいです。

C#
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i}: {names[i]}");
}

どうしてもforeachでインデックスを使いたい場合は、別の変数を用意します。

C#
int index = 0;

foreach (string name in names)
{
Console.WriteLine($"{index}: {name}");
index++;
}

また、LINQのSelectを使う方法もあります。

C#
foreach (var item in names.Select((name, index) => new { name, index }))
{
Console.WriteLine($"{item.index}: {item.name}");
}

初心者には、まずfor文を使う方法がおすすめです。

11-4. ループを途中で抜けるには?

ループを途中で抜けるにはbreakを使います。

C#
foreach (string name in names)
{
if (name == "佐藤")
{
break;
}

Console.WriteLine(name);
}

条件に合う要素が見つかったらループを終了したい場合などに使います。

メソッドごと終了したい場合はreturnを使います。

C#
static void CheckName(List<string> names)
{
foreach (string name in names)
{
if (name == "佐藤")
{
Console.WriteLine("見つかりました");
return;
}
}

Console.WriteLine("見つかりませんでした");
}

breakはループだけを終了し、returnはメソッド全体を終了する点が違います。

11-5. 無限ループが起きたときはどうすればいい?

無限ループが起きた場合は、まずループの条件式と変数の更新処理を確認しましょう。

C#
int count = 0;

while (count < 10)
{
Console.WriteLine(count);
}

このコードでは、count++がないため無限ループになります。

正しくは次のように書きます。

C#
int count = 0;

while (count < 10)
{
Console.WriteLine(count);
count++;
}

また、while (true)を使う場合は、必ずbreakで抜ける条件を用意します。

C#
while (true)
{
string input = Console.ReadLine();

if (input == "exit")
{
break;
}
}

無限ループが発生したら、次の点を確認してください。

確認すること内容
条件式いつfalseになるか
変数更新条件に関係する値が変化しているか
break終了条件が用意されているか
入力値想定どおりの値が入っているか

開発環境で実行中のプログラムが止まらない場合は、停止ボタンで実行を中断し、条件式を見直しましょう。

まとめ

C#のループ処理は、同じ処理を効率よく繰り返すための重要な仕組みです。

C#で使う代表的なループには、for文、foreach文、while文、do-while文があります。

それぞれの使い分けは次のとおりです。

ループ使う場面
for回数が決まっている、インデックスを使う
foreach配列やListなどの全要素を順番に処理する
while条件を満たすまで繰り返す
do-while最低1回は処理を実行する

初心者が特に注意したいポイントは、条件式の書き間違い、インデックス範囲外エラー、無限ループ、foreach中のコレクション変更です。

まずは、次の基準で使い分けるとよいでしょう。

C#
// 回数が決まっている
for

// コレクションの全要素を処理する
foreach

// 条件を満たすまで繰り返す
while

// 最低1回実行する
do-while

C#のループは、配列、List、Dictionary、入力チェック、検索、集計など、実務でも頻繁に使われます。基本構文を覚えるだけでなく、「どのループを使うと読みやすいか」まで意識すると、より実践的なコードを書けるようになります。