C#のloop完全ガイド|for・foreach・whileの違いと使い分けを初心者向けに解説
はじめに
C#でプログラムを書くとき、必ずと言ってよいほど登場するのが「loop」、つまり繰り返し処理です。
たとえば、次のような処理を考えてみましょう。
C#Console.WriteLine("こんにちは");
Console.WriteLine("こんにちは");
Console.WriteLine("こんにちは");
Console.WriteLine("こんにちは");
Console.WriteLine("こんにちは");
同じ処理を何度も書くと、コードが長くなり、修正もしにくくなります。このようなときに使うのがC#のloopです。
C#には、主に次のループ構文があります。
C#for
foreach
while
do while
それぞれ得意な場面が異なるため、違いを理解して使い分けることが大切です。
この記事では、C#のloopについて、初心者にもわかりやすく、for・foreach・while・do whileの違いや使い分け、実践例、つまずきやすいポイントまで解説します。
1. C#のloopとは?初心者が最初に押さえる基本
C#のloopとは、同じ処理や似た処理を繰り返し実行するための仕組みです。
プログラムでは、配列の中身を1つずつ表示したり、条件を満たすまで入力を繰り返したり、決まった回数だけ処理を実行したりする場面がよくあります。
そのような処理を効率よく書くために、C#では複数のループ構文が用意されています。
1-1. loopは同じ処理を繰り返すための仕組み
loopを使うと、同じ処理を何度も手書きする必要がなくなります。
たとえば、1から5までの数字を表示する処理は、次のように書けます。
C#for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
実行結果は次のようになります。
1
2
3
4
5
このコードでは、Console.WriteLine(i);という処理を、iの値を変えながら5回繰り返しています。
もしloopを使わなければ、次のように書く必要があります。
C#Console.WriteLine(1);
Console.WriteLine(2);
Console.WriteLine(3);
Console.WriteLine(4);
Console.WriteLine(5);
5回程度ならまだ書けますが、100回、1000回になると現実的ではありません。C#のloopを使えば、短く読みやすいコードで繰り返し処理を実現できます。
1-2. C#で使う主なループ構文:for・foreach・while・do while
C#でよく使うloopには、次の4種類があります。
C#for
foreach
while
do while
それぞれの特徴は次のとおりです。
for :回数が決まっている繰り返しに向いている
foreach :配列やListなどの要素を順番に処理するのに向いている
while :条件を満たす間だけ繰り返す処理に向いている
do while :最低1回は処理を実行したいときに向いている
初心者のうちは、まずforとforeachをしっかり理解するとよいでしょう。配列やListを扱う場面では、この2つを使うことが非常に多いです。
そのうえで、条件によって繰り返す処理が必要になったらwhile、最低1回は実行したい処理がある場合はdo whileを使うと理解しやすくなります。
1-3. ループ処理でよく出てくる「条件式」「カウンター」「コレクション」
C#のloopを理解するうえで、よく出てくる言葉があります。
まず「条件式」です。条件式とは、ループを続けるかどうかを判断する式です。
C#i < 10
number != 0
isRunning == true
条件式がtrueの間、ループは続きます。条件式がfalseになると、ループは終了します。
次に「カウンター」です。カウンターとは、繰り返しの回数を数えるための変数です。for文では、よくiという名前の変数が使われます。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
この場合、iがカウンター変数です。
最後に「コレクション」です。コレクションとは、複数のデータをまとめて扱うものです。C#では、配列やList、Dictionaryなどがよく使われます。
C#string[] names = { "佐藤", "鈴木", "田中" };
List<int> scores = new List<int> { 80, 90, 75 };
Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "佐藤", 25 },
{ "鈴木", 30 }
};
foreach文は、このようなコレクションを1つずつ処理するときに便利です。
1-4. for・foreach・whileの使い分け早見表
C#のloopを使い分けるときは、次のように考えるとわかりやすいです。
| 使いたい場面 | おすすめのループ |
|---|---|
| 10回繰り返したい | for |
| 配列やListの要素を順番に処理したい | foreach |
| 条件を満たす間だけ繰り返したい | while |
| 最低1回は処理を実行したい | do while |
| インデックス番号を使いたい | for |
| 要素の中身だけ使えればよい | foreach |
| ユーザー入力を繰り返したい | while / do while |
たとえば、「配列のすべての要素を表示したい」ならforeachが自然です。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
一方、「0番目、1番目、2番目のようにインデックスを使いたい」ならforが向いています。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"{i}: {fruits[i]}");
}
C#のloopでは、「何を基準に繰り返すのか」を考えると、適切な構文を選びやすくなります。
2. C#のfor文|回数が決まっている繰り返しに使う
C#のfor文は、繰り返す回数があらかじめ決まっている場合に使いやすいループ構文です。
たとえば、次のような処理に向いています。
1から10まで表示する
配列の0番目から最後まで順番に処理する
10回だけ同じ処理を実行する
2つ飛ばしで数値を処理する
逆順にデータを処理する
for文は、カウンター変数を使って繰り返しを制御します。
2-1. for文の基本構文
C#のfor文の基本構文は次のとおりです。
C#for (初期化; 条件式; 更新処理)
{
繰り返したい処理;
}
具体的には、次のように書きます。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
このfor文は、次の流れで動きます。
1. int i = 0 でカウンター変数を作る
2. i < 5 が true か確認する
3. trueならループ内の処理を実行する
4. i++ でiを1増やす
5. もう一度 i < 5 を確認する
6. 条件が false になるまで繰り返す
i < 5がfalseになると、for文は終了します。
2-2. for文のサンプルコード
1から5までの数字を表示するfor文を見てみましょう。
C#for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
実行結果は次のとおりです。
1
2
3
4
5
このコードでは、iが1から始まり、5以下の間だけ処理を繰り返します。処理が1回終わるたびに、i++によってiが1ずつ増えます。
0から始めたい場合は、次のように書きます。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
実行結果は次のようになります。
0
1
2
3
4
C#では、配列やListのインデックスが0から始まるため、for (int i = 0; i < count; i++)という書き方がよく使われます。
2-3. カウンター変数iの意味と動き
for文でよく使われるiは、カウンター変数です。iという名前には特別な機能があるわけではありません。
次のように、別の名前にしても動作します。
C#for (int count = 0; count < 5; count++)
{
Console.WriteLine(count);
}
ただし、短いfor文では慣習的にiがよく使われます。
ネストしたループでは、外側にi、内側にjを使うこともあります。
C#for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
Console.WriteLine($"i={i}, j={j}");
}
}
i++は、iの値を1増やすという意味です。
C#i++;
これは、次のコードと同じ意味です。
C#i = i + 1;
for文では、この更新処理によってカウンター変数を変化させ、いつか条件式がfalseになるようにします。
2-4. 配列やListをインデックスで処理する方法
for文は、配列やListをインデックスで処理したいときに便利です。
配列をfor文で処理する例です。
C#string[] names = { "佐藤", "鈴木", "田中" };
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}
配列の要素数はLengthで取得します。
C#names.Length
Listの場合は、要素数をCountで取得します。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine(names[i]);
}
配列ではLength、ListではCountを使う点に注意しましょう。
インデックス番号も一緒に表示したい場合は、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番目: 田中
2-5. 逆順ループ・2つ飛ばしループの書き方
for文では、カウンター変数の増減を自由に設定できます。
逆順にループしたい場合は、次のように書きます。
C#for (int i = 5; i >= 1; i--)
{
Console.WriteLine(i);
}
実行結果は次のとおりです。
5
4
3
2
1
i--は、iを1減らすという意味です。
配列を後ろから処理する場合は、次のように書きます。
C#string[] names = { "佐藤", "鈴木", "田中" };
for (int i = names.Length - 1; i >= 0; i--)
{
Console.WriteLine(names[i]);
}
実行結果は次のようになります。
田中
鈴木
佐藤
2つ飛ばしでループする場合は、更新処理をi += 2にします。
C#for (int i = 0; i <= 10; i += 2)
{
Console.WriteLine(i);
}
実行結果は次のとおりです。
0
2
4
6
8
10
このように、for文はカウンターの動きを細かく制御したいときに便利です。
2-6. for文を使うべきケース
C#でfor文を使うべきケースは、主に次のような場面です。
繰り返す回数が決まっている
インデックス番号が必要
配列やListを番号で参照したい
逆順で処理したい
1つ飛ばし、2つ飛ばしなど特殊な進み方をしたい
たとえば、配列の偶数番目だけ処理する場合は、for文が向いています。
C#string[] items = { "A", "B", "C", "D", "E" };
for (int i = 0; i < items.Length; i += 2)
{
Console.WriteLine(items[i]);
}
一方で、単にすべての要素を順番に処理したいだけなら、foreach文のほうが読みやすい場合が多いです。
C#foreach (string item in items)
{
Console.WriteLine(item);
}
for文は強力ですが、すべてのloopをfor文で書く必要はありません。目的に応じて、foreachやwhileと使い分けましょう。
3. C#のforeach文|配列やListの要素を順番に処理する
C#のforeach文は、配列やListなどのコレクションの要素を、先頭から順番に取り出して処理するためのループ構文です。
for文のようにインデックス番号を意識する必要がないため、初心者にも読みやすい書き方です。
たとえば、配列の中身をすべて表示する場合、foreach文を使うと次のように書けます。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
「コレクションの中身を1つずつ処理したい」ときは、まずforeach文を検討するとよいでしょう。
3-1. foreach文の基本構文
foreach文の基本構文は次のとおりです。
C#foreach (型 変数名 in コレクション)
{
繰り返したい処理;
}
具体的には、次のように書きます。
C#foreach (string name in names)
{
Console.WriteLine(name);
}
このコードでは、namesの中から要素を1つずつ取り出し、nameという変数に入れて処理します。
たとえば、次の配列があるとします。
C#string[] names = { "佐藤", "鈴木", "田中" };
foreach文は、次のように動きます。
1回目:name に "佐藤" が入る
2回目:name に "鈴木" が入る
3回目:name に "田中" が入る
要素がすべて処理されると、foreach文は終了します。
3-2. foreach文のサンプルコード
整数のListをforeach文で処理する例です。
C#List<int> scores = new List<int> { 80, 90, 75 };
foreach (int score in scores)
{
Console.WriteLine(score);
}
実行結果は次のようになります。
80
90
75
foreach文では、カウンター変数を自分で用意する必要がありません。そのため、「全要素を順番に処理する」という目的がはっきり伝わるコードになります。
合計値を求める処理も、foreach文でわかりやすく書けます。
C#List<int> scores = new List<int> { 80, 90, 75 };
int total = 0;
foreach (int score in scores)
{
total += score;
}
Console.WriteLine(total);
実行結果は次のとおりです。
245
3-3. 配列をforeachでループする方法
配列をforeachでループする場合は、次のように書きます。
C#string[] colors = { "赤", "青", "緑" };
foreach (string color in colors)
{
Console.WriteLine(color);
}
実行結果は次のとおりです。
赤
青
緑
配列の要素をすべて処理したいだけであれば、for文よりもforeach文のほうがシンプルです。
for文で書くと、次のようになります。
C#for (int i = 0; i < colors.Length; i++)
{
Console.WriteLine(colors[i]);
}
このコードも正しく動きますが、インデックスが不要な場合は、foreach文のほうが読みやすいです。
C#foreach (string color in colors)
{
Console.WriteLine(color);
}
C#のloopでは、読みやすさも重要です。単純に配列の要素を順番に処理するなら、foreach文を使うと意図が伝わりやすくなります。
3-4. Listをforeachでループする方法
Listもforeach文で簡単に処理できます。
C#List<string> users = new List<string>
{
"佐藤",
"鈴木",
"田中"
};
foreach (string user in users)
{
Console.WriteLine(user);
}
実行結果は次のようになります。
佐藤
鈴木
田中
Listの中から条件に合う要素だけ処理することもできます。
C#List<int> scores = new List<int> { 80, 45, 90, 60, 30 };
foreach (int score in scores)
{
if (score >= 60)
{
Console.WriteLine($"合格: {score}");
}
}
実行結果は次のとおりです。
合格: 80
合格: 90
合格: 60
foreach文は、Listの中身を読み取って処理する場面で特に便利です。
3-5. Dictionaryをforeachでループする方法
C#のDictionaryもforeach文でループできます。
Dictionaryは、キーと値の組み合わせでデータを管理するコレクションです。
C#Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "佐藤", 25 },
{ "鈴木", 30 },
{ "田中", 28 }
};
foreachで処理する場合は、次のように書きます。
C#foreach (KeyValuePair<string, int> pair in ages)
{
Console.WriteLine($"{pair.Key}: {pair.Value}歳");
}
実行結果は次のとおりです。
佐藤: 25歳
鈴木: 30歳
田中: 28歳
C#では、次のように型推論のvarを使って書くこともよくあります。
C#foreach (var pair in ages)
{
Console.WriteLine($"{pair.Key}: {pair.Value}歳");
}
pair.Keyでキーを取得し、pair.Valueで値を取得できます。
キーだけを処理したい場合は、Keysを使います。
C#foreach (string name in ages.Keys)
{
Console.WriteLine(name);
}
値だけを処理したい場合は、Valuesを使います。
C#foreach (int age in ages.Values)
{
Console.WriteLine(age);
}
3-6. foreach文でインデックスが必要なときの対処法
foreach文は、基本的にインデックスを使わずに要素を処理するための構文です。
しかし、処理の中で「何番目の要素か」を知りたい場合もあります。その場合は、カウンター変数を別に用意できます。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
int index = 0;
foreach (string name in names)
{
Console.WriteLine($"{index}: {name}");
index++;
}
実行結果は次のようになります。
0: 佐藤
1: 鈴木
2: 田中
ただし、インデックスを頻繁に使うなら、for文のほうが自然です。
C#for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i}: {names[i]}");
}
つまり、次のように考えるとよいでしょう。
インデックスが不要 → foreach
インデックスが必要 → for
3-7. foreach文を使うべきケース
foreach文を使うべきケースは、主に次のような場面です。
配列の全要素を処理したい
Listの全要素を処理したい
Dictionaryのキーと値を順番に処理したい
インデックス番号が不要
コードを読みやすくしたい
たとえば、Listに入っている名前をすべて表示するだけなら、foreach文が最適です。
C#foreach (string name in names)
{
Console.WriteLine(name);
}
for文でも書けますが、インデックスが不要であれば、foreach文のほうが意図が明確です。
一方で、Listの要素を削除しながらループしたい場合は、foreach文には注意が必要です。foreach中にListの要素を追加・削除すると、例外が発生することがあります。
そのため、要素を読み取るだけならforeach、インデックス操作や削除が必要ならfor文を検討しましょう。
4. C#のwhile文|条件を満たす間だけ繰り返す
C#のwhile文は、条件式がtrueの間だけ処理を繰り返すループ構文です。
for文は回数が決まっている繰り返しに向いていますが、while文は「いつ終わるかわからない処理」に向いています。
たとえば、次のような場面で使います。
正しい入力があるまで繰り返す
特定の条件が満たされるまで待つ
ファイルの終わりまで読み込む
ゲームが続いている間だけ処理する
while文では、条件式が重要です。条件式がずっとtrueのままだと、無限ループになるため注意が必要です。
4-1. while文の基本構文
while文の基本構文は次のとおりです。
C#while (条件式)
{
繰り返したい処理;
}
条件式がtrueの場合、ループ内の処理が実行されます。処理が終わると、再び条件式を確認します。
条件式がfalseになると、while文は終了します。
C#int count = 0;
while (count < 5)
{
Console.WriteLine(count);
count++;
}
実行結果は次のようになります。
0
1
2
3
4
このコードでは、count < 5がtrueの間だけ処理が繰り返されます。
4-2. while文のサンプルコード
1から5まで表示するwhile文の例です。
C#int number = 1;
while (number <= 5)
{
Console.WriteLine(number);
number++;
}
実行結果は次のとおりです。
1
2
3
4
5
for文で書くと、次のようになります。
C#for (int number = 1; number <= 5; number++)
{
Console.WriteLine(number);
}
このように、回数が決まっている場合はfor文のほうがコンパクトです。
一方で、条件によって繰り返しを続けるかどうかを判断したい場合は、while文が向いています。
C#int hp = 100;
while (hp > 0)
{
Console.WriteLine($"HP: {hp}");
hp -= 30;
}
Console.WriteLine("終了");
実行結果は次のようになります。
HP: 100
HP: 70
HP: 40
HP: 10
終了
この例では、hp > 0の間だけループが続きます。
4-3. while文とfor文の違い
while文とfor文は、どちらも繰り返し処理を行うための構文です。
大きな違いは、繰り返し回数が明確かどうかです。
for文は、回数が決まっている処理に向いています。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
このコードは、10回繰り返すことがすぐにわかります。
一方、while文は条件を満たす間だけ繰り返します。
C#while (isRunning)
{
// 処理
}
この場合、何回繰り返すかはisRunningの値によって変わります。
使い分けの目安は次のとおりです。
繰り返し回数が決まっている → for
繰り返し回数が条件によって変わる → while
ただし、while文でも回数が決まった処理は書けます。
C#int i = 0;
while (i < 10)
{
Console.WriteLine(i);
i++;
}
しかし、このような処理はfor文のほうが読みやすいことが多いです。
4-4. 入力チェックや条件待ちでwhile文を使う例
while文は、ユーザー入力を繰り返しチェックする処理でよく使われます。
次の例では、ユーザーがexitと入力するまで、入力を受け付け続けます。
C#string input = "";
while (input != "exit")
{
Console.Write("文字を入力してください。終了するには exit と入力: ");
input = Console.ReadLine();
Console.WriteLine($"入力内容: {input}");
}
この処理では、input != "exit"がtrueの間、ループが続きます。
数値入力をチェックする例も見てみましょう。
C#int number;
bool success = false;
while (!success)
{
Console.Write("数値を入力してください: ");
string input = Console.ReadLine();
success = int.TryParse(input, out number);
}
Console.WriteLine("正しい数値が入力されました。");
int.TryParseは、文字列を数値に変換できるかどうかを判定するメソッドです。変換に成功するとtrueを返します。
このように、正しい入力があるまで繰り返したい場合、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++;
}
while文を書くときは、次の点を確認しましょう。
条件式がいつか false になるか
ループ内で条件に関係する変数が更新されているか
breakで終了できる設計になっているか
意図的に無限ループを書く場合もありますが、その場合でも終了条件やbreakを用意するのが基本です。
4-6. while文を使うべきケース
while文を使うべきケースは、次のような場面です。
繰り返す回数が事前にわからない
条件を満たす間だけ処理したい
ユーザー入力を繰り返したい
状態が変わるまで処理を続けたい
たとえば、ログイン成功まで入力を繰り返すような処理は、while文が向いています。
C#bool loggedIn = false;
while (!loggedIn)
{
Console.Write("パスワードを入力してください: ");
string password = Console.ReadLine();
if (password == "secret")
{
loggedIn = true;
}
}
このように、回数ではなく条件でループを制御したい場合は、while文を使うと自然です。
5. C#のdo while文|最低1回は実行したいときに使う
C#のdo while文は、while文と同じく条件を満たす間だけ繰り返すループ構文です。
ただし、while文との大きな違いは、条件判定のタイミングです。
while文は、最初に条件を確認してから処理を実行します。一方、do while文は、先に処理を実行してから条件を確認します。
そのため、do while文は最低1回は必ず処理を実行します。
5-1. do while文の基本構文
do while文の基本構文は次のとおりです。
C#do
{
繰り返したい処理;
}
while (条件式);
最後のwhile (条件式);の後ろにセミコロンが必要です。
サンプルを見てみましょう。
C#int count = 0;
do
{
Console.WriteLine(count);
count++;
}
while (count < 5);
実行結果は次のとおりです。
0
1
2
3
4
この例では、count < 5がtrueの間、処理を繰り返します。
5-2. while文とdo while文の違い
while文とdo while文の違いは、条件式を確認するタイミングです。
while文は、処理の前に条件を確認します。
C#int count = 10;
while (count < 5)
{
Console.WriteLine(count);
}
このコードでは、最初からcount < 5がfalseなので、ループ内の処理は1回も実行されません。
一方、do while文は、処理の後に条件を確認します。
C#int count = 10;
do
{
Console.WriteLine(count);
}
while (count < 5);
このコードでは、条件式がfalseでも、最初の1回は必ず実行されます。
実行結果は次のとおりです。
10
つまり、次のように使い分けます。
条件を満たす場合だけ実行したい → while
最低1回は実行したい → do while
5-3. do while文のサンプルコード
ユーザーに数値を入力してもらい、0が入力されるまで繰り返す例です。
C#int number;
do
{
Console.Write("数値を入力してください。終了するには0を入力: ");
string input = Console.ReadLine();
number = int.Parse(input);
Console.WriteLine($"入力された数値: {number}");
}
while (number != 0);
この処理では、まずユーザー入力を受け取ります。その後、number != 0かどうかを判定します。
最初に入力を受け取る必要があるため、do while文が使いやすいケースです。
ただし、実際の開発では、int.Parseは入力が数値でない場合に例外が発生するため、int.TryParseを使うことが多いです。
C#int number;
do
{
Console.Write("数値を入力してください。終了するには0を入力: ");
string input = Console.ReadLine();
if (int.TryParse(input, out number))
{
Console.WriteLine($"入力された数値: {number}");
}
else
{
Console.WriteLine("数値を入力してください。");
number = -1;
}
}
while (number != 0);
5-4. メニュー選択や再入力処理で使う例
do while文は、メニュー選択のように「まずメニューを表示し、その後で続けるか判断する」処理に向いています。
C#int choice;
do
{
Console.WriteLine("メニューを選択してください");
Console.WriteLine("1: 開始");
Console.WriteLine("2: 設定");
Console.WriteLine("0: 終了");
Console.Write("選択: ");
string input = Console.ReadLine();
int.TryParse(input, out choice);
switch (choice)
{
case 1:
Console.WriteLine("開始します");
break;
case 2:
Console.WriteLine("設定を開きます");
break;
case 0:
Console.WriteLine("終了します");
break;
default:
Console.WriteLine("正しい番号を選択してください");
break;
}
}
while (choice != 0);
このコードでは、メニューを最低1回は表示します。ユーザーが0を選ぶまで、メニューが繰り返し表示されます。
このような処理では、do while文を使うと自然な流れで書けます。
5-5. do while文を使うべきケース
do while文を使うべきケースは、次のような場面です。
最低1回は処理を実行したい
最初に入力を受け取ってから条件を判定したい
メニューを表示してから終了判定したい
再入力処理を作りたい
while文でも同じような処理は書けますが、先に1回処理を実行する必要がある場合は、do while文のほうが意図が伝わりやすくなります。
ただし、do while文はfor文やforeach文ほど頻繁に使われるわけではありません。必要な場面で使えるように、特徴を押さえておきましょう。
6. for・foreach・whileの違いと使い分け
C#のloopで初心者が迷いやすいのが、for・foreach・while・do whileの使い分けです。
どれを使っても似たような処理を書ける場合がありますが、読みやすさや目的に合った構文を選ぶことが大切です。
基本的には、次のように考えるとわかりやすいです。
回数が決まっている → for
配列やListを順番に処理する → foreach
条件次第で繰り返す → while
最低1回は実行する → do while
6-1. 回数が決まっているならfor
繰り返す回数がはっきり決まっている場合は、for文が向いています。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine("Hello");
}
このコードは、Helloを10回表示します。
for文は、初期化、条件式、更新処理が1行にまとまっているため、何回繰り返すのかが読み取りやすいです。
配列やListをインデックスで処理する場合にも便利です。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i}: {names[i]}");
}
インデックス番号が必要な処理では、foreachよりfor文のほうが自然です。
6-2. 配列やListを順番に処理するならforeach
配列やListの要素を順番に処理したい場合は、foreach文が向いています。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
foreach (string name in names)
{
Console.WriteLine(name);
}
このコードは、Listの中身を1つずつ取り出して表示します。
foreach文は、インデックスを意識しなくてよいため、コードがシンプルになります。
「全要素を順番に処理する」という目的であれば、foreach文を使うと読みやすくなります。
6-3. 条件次第で繰り返すならwhile
繰り返す回数が事前にわからず、条件によって処理を続けるかどうかを決めたい場合は、while文が向いています。
C#string input = "";
while (input != "exit")
{
Console.Write("入力してください: ");
input = Console.ReadLine();
}
このコードでは、ユーザーがexitと入力するまでループが続きます。
何回繰り返すかは、ユーザーの入力によって変わります。
このように、回数ではなく条件で制御する場合はwhile文を使うとよいでしょう。
6-4. 最低1回実行したいならdo while
処理を最低1回は実行したい場合は、do while文が向いています。
C#string input;
do
{
Console.Write("入力してください。終了するには exit: ");
input = Console.ReadLine();
}
while (input != "exit");
このコードでは、最初の入力受付は必ず実行されます。その後、input != "exit"がtrueなら繰り返します。
メニュー表示や再入力処理では、do while文が自然に使える場面があります。
6-5. 読みやすさで選ぶループ構文
C#のloopでは、単に動けばよいというわけではありません。読みやすいコードを書くことも重要です。
たとえば、配列の全要素を表示するだけなら、for文でもforeach文でも書けます。
C#string[] fruits = { "りんご", "バナナ", "みかん" };
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine(fruits[i]);
}
C#foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
どちらも正しく動きますが、インデックスが不要であればforeach文のほうが読みやすいです。
逆に、インデックスを使う処理ならfor文のほうが適しています。
C#for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"{i + 1}: {fruits[i]}");
}
適切なloopを選ぶことで、コードの意図が伝わりやすくなります。
6-6. 初心者が迷ったときの判断基準
初心者がC#のloopで迷ったときは、次の順番で考えると判断しやすいです。
まず、配列やListなどの全要素を処理したいだけなら、foreach文を使います。
C#foreach (var item in items)
{
Console.WriteLine(item);
}
次に、インデックスが必要ならfor文を使います。
C#for (int i = 0; i < items.Count; i++)
{
Console.WriteLine($"{i}: {items[i]}");
}
回数が決まっている場合もfor文です。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
何回繰り返すかわからない場合はwhile文を使います。
C#while (condition)
{
// 条件が true の間だけ繰り返す
}
最低1回実行したいならdo while文を使います。
C#do
{
// 最低1回は実行する
}
while (condition);
迷ったら、「回数」「コレクション」「条件」「最低1回」の4つを基準に考えましょう。
7. C#のloopで使う制御文
C#のloopでは、ループの途中で処理を止めたり、次の繰り返しに進んだりするための制御文があります。
主に使うのは、次の3つです。
C#break
continue
return
それぞれ役割が違うため、正しく使い分けることが大切です。
7-1. breakでループを途中終了する
breakは、ループを途中で終了するための制御文です。
たとえば、Listの中から特定の値を見つけたらループを終了する場合に使います。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
foreach (string name in names)
{
if (name == "鈴木")
{
Console.WriteLine("鈴木さんを見つけました");
break;
}
Console.WriteLine(name);
}
実行結果は次のようになります。
佐藤
鈴木さんを見つけました
breakが実行されると、foreach文はその時点で終了します。
while文でもbreakは使えます。
C#while (true)
{
Console.Write("終了するには exit と入力: ");
string input = Console.ReadLine();
if (input == "exit")
{
break;
}
}
このように、条件を満たしたらループを抜けたい場合にbreakを使います。
7-2. continueで次の繰り返しにスキップする
continueは、現在の繰り返し処理を途中でスキップして、次の繰り返しに進むための制御文です。
たとえば、偶数だけ処理したい場合は次のように書けます。
C#for (int i = 1; i <= 10; i++)
{
if (i % 2 != 0)
{
continue;
}
Console.WriteLine(i);
}
実行結果は次のとおりです。
2
4
6
8
10
このコードでは、iが奇数の場合にcontinueが実行されます。そのため、Console.WriteLine(i);はスキップされます。
foreach文でも使えます。
C#List<int> scores = new List<int> { 80, 45, 90, 30, 70 };
foreach (int score in scores)
{
if (score < 60)
{
continue;
}
Console.WriteLine($"合格: {score}");
}
条件に合わないデータをスキップしたいときに、continueは便利です。
7-3. returnでメソッドごと終了する
returnは、ループだけでなく、メソッド全体を終了します。
たとえば、特定の値が見つかったら、その時点でメソッドを終了する場合に使います。
C#static bool ContainsName(List<string> names, string target)
{
foreach (string name in names)
{
if (name == target)
{
return true;
}
}
return false;
}
このメソッドでは、targetと一致する名前が見つかった時点でreturn true;が実行され、メソッドが終了します。
見つからなかった場合は、最後にreturn false;が実行されます。
returnはループを抜けるだけではなく、メソッド自体を終了する点が重要です。
7-4. break・continue・returnの違い
break、continue、returnの違いを整理すると、次のようになります。
| 制御文 | 動き |
|---|---|
| break | ループを終了する |
| continue | 今回の処理をスキップして次の繰り返しへ進む |
| return | メソッド全体を終了する |
次のコードで違いを確認しましょう。
C#for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
break;
}
Console.WriteLine(i);
}
実行結果は次のとおりです。
1
2
i == 3でループが終了します。
次に、continueの場合です。
C#for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
continue;
}
Console.WriteLine(i);
}
実行結果は次のようになります。
1
2
4
5
i == 3の回だけスキップされます。
returnの場合は、メソッド自体が終了します。
C#static void PrintNumbers()
{
for (int i = 1; i <= 5; i++)
{
if (i == 3)
{
return;
}
Console.WriteLine(i);
}
Console.WriteLine("ループ終了");
}
この場合、i == 3でメソッドが終了するため、ループ終了も表示されません。
7-5. ネストしたループでbreakを使うときの注意点
ループの中にループを書くことを、ネストしたループと呼びます。
C#for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.WriteLine($"i={i}, j={j}");
}
}
ネストしたループでbreakを使うと、終了するのは内側のループだけです。
C#for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (j == 1)
{
break;
}
Console.WriteLine($"i={i}, j={j}");
}
}
このコードでは、j == 1になると内側のループだけが終了します。外側のループは続きます。
実行結果は次のようになります。
i=0, j=0
i=1, j=0
i=2, j=0
外側のループも含めて終了したい場合は、フラグ変数を使う方法があります。
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;
}
}
ネストが深いループでは、breakの動きを誤解しやすいため注意しましょう。
8. C#のloop実践例
ここからは、C#のloopを使った実践例を紹介します。
for、foreach、while、do whileを実際の処理に近い形で見ていくことで、使い分けが理解しやすくなります。
8-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
回数が決まっているため、for文が適しています。
while文でも書けます。
C#int i = 1;
while (i <= 10)
{
Console.WriteLine(i);
i++;
}
ただし、このような単純な回数指定の繰り返しでは、for文のほうが読みやすいです。
8-2. 配列の合計値を計算する
配列の合計値を計算する場合は、foreach文が便利です。
C#int[] numbers = { 10, 20, 30, 40, 50 };
int total = 0;
foreach (int number in numbers)
{
total += number;
}
Console.WriteLine($"合計: {total}");
実行結果は次のとおりです。
合計: 150
配列の各要素を順番に取り出して、totalに加算しています。
for文で書くこともできます。
C#int[] numbers = { 10, 20, 30, 40, 50 };
int total = 0;
for (int i = 0; i < numbers.Length; i++)
{
total += numbers[i];
}
Console.WriteLine($"合計: {total}");
インデックスが不要な場合は、foreach文のほうがシンプルです。
8-3. Listの中から条件に合う要素を探す
Listの中から条件に合う要素を探す場合は、foreach文とif文を組み合わせます。
C#List<string> names = new List<string>
{
"佐藤",
"鈴木",
"田中",
"高橋"
};
foreach (string name in names)
{
if (name == "田中")
{
Console.WriteLine("田中さんを見つけました");
break;
}
}
条件に合う要素を見つけた時点でbreakを使うと、不要なループを続けずに済みます。
数値のListから、最初に60点以上の点数を探す例も見てみましょう。
C#List<int> scores = new List<int> { 45, 50, 72, 80 };
foreach (int score in scores)
{
if (score >= 60)
{
Console.WriteLine($"最初の合格点: {score}");
break;
}
}
実行結果は次のとおりです。
最初の合格点: 72
8-4. ユーザー入力を繰り返し受け取る
ユーザー入力を繰り返し受け取る場合は、while文がよく使われます。
C#string input = "";
while (input != "exit")
{
Console.Write("文字を入力してください。終了するには exit: ");
input = Console.ReadLine();
Console.WriteLine($"入力: {input}");
}
このコードでは、ユーザーがexitと入力するまで処理が続きます。
メニュー形式にするなら、do while文も使えます。
C#int choice;
do
{
Console.WriteLine("1: 開始");
Console.WriteLine("2: 設定");
Console.WriteLine("0: 終了");
Console.Write("選択してください: ");
string input = Console.ReadLine();
int.TryParse(input, out choice);
Console.WriteLine($"選択: {choice}");
}
while (choice != 0);
メニューを最低1回表示したい場合は、do while文が向いています。
8-5. 2重ループで表や九九を作る
2重ループを使うと、表のようなデータを作れます。
九九を表示する例です。
C#for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
Console.Write($"{i * j}\t");
}
Console.WriteLine();
}
外側のループは行を表し、内側のループは列を表します。
i: 1から9まで
j: 1から9まで
i * j: 九九の結果
2重ループでは、外側と内側の役割を意識することが大切です。
シンプルな表を作る例も見てみましょう。
C#for (int row = 1; row <= 3; row++)
{
for (int column = 1; column <= 4; column++)
{
Console.Write($"({row},{column}) ");
}
Console.WriteLine();
}
実行結果は次のようになります。
(1,1) (1,2) (1,3) (1,4)
(2,1) (2,2) (2,3) (2,4)
(3,1) (3,2) (3,3) (3,4)
8-6. 条件に合う要素だけ処理する
条件に合う要素だけ処理したい場合は、if文とcontinueを組み合わせると便利です。
C#List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
foreach (int number in numbers)
{
if (number % 2 != 0)
{
continue;
}
Console.WriteLine(number);
}
実行結果は次のとおりです。
2
4
6
このコードでは、奇数の場合はcontinueでスキップし、偶数だけ表示しています。
if文だけで書くこともできます。
C#foreach (int number in numbers)
{
if (number % 2 == 0)
{
Console.WriteLine(number);
}
}
どちらも正しく動きます。処理が短い場合は、if文だけのほうが読みやすいこともあります。
9. C#のloopで初心者がつまずきやすいポイント
C#のloopは便利ですが、初心者がつまずきやすいポイントもあります。
特に、カウンター変数、条件式、無限ループ、foreach中の変更、nullの扱いには注意が必要です。
9-1. i++と++iの違い
i++と++iは、どちらもiを1増やす処理です。
C#i++;
++i;
単独で使う場合、結果は同じです。
C#int i = 0;
i++;
Console.WriteLine(i);
1
C#int i = 0;
++i;
Console.WriteLine(i);
1
違いが出るのは、値を使いながら増やす場合です。
C#int i = 0;
int a = i++;
Console.WriteLine(a);
Console.WriteLine(i);
実行結果は次のとおりです。
0
1
i++は、先に現在の値を使ってから、後で1増やします。
一方、++iは、先に1増やしてから値を使います。
C#int i = 0;
int a = ++i;
Console.WriteLine(a);
Console.WriteLine(i);
実行結果は次のとおりです。
1
1
ただし、for文の更新処理で使う場合は、ほとんどの場合どちらでも動きは同じです。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
初心者のうちは、一般的によく使われるi++を覚えておけば十分です。
9-2. i < countとi <= countの違い
C#のfor文でよくあるミスが、i < countとi <= countの違いです。
Listの要素数が3の場合、インデックスは次のようになります。
0
1
2
つまり、最後のインデックスはCount - 1です。
正しい書き方は次のとおりです。
C#List<string> names = new List<string> { "佐藤", "鈴木", "田中" };
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine(names[i]);
}
i < names.Countなので、iは0、1、2まで進みます。
間違ってi <= names.Countと書くと、iが3のときにも処理が実行されます。
C#for (int i = 0; i <= names.Count; i++)
{
Console.WriteLine(names[i]);
}
しかし、names[3]は存在しないため、エラーになります。
配列やListをインデックスで処理するときは、基本的に次の形を使いましょう。
C#for (int i = 0; i < items.Count; i++)
{
// items[i] を処理
}
配列の場合は次の形です。
C#for (int i = 0; i < items.Length; i++)
{
// items[i] を処理
}
9-3. 無限ループが起きる原因
無限ループは、ループの終了条件が満たされず、処理が終わらない状態です。
たとえば、次のコードは無限ループになります。
C#int i = 0;
while (i < 10)
{
Console.WriteLine(i);
}
iが増えないため、i < 10がずっとtrueのままです。
正しくは、ループ内でiを増やします。
C#int i = 0;
while (i < 10)
{
Console.WriteLine(i);
i++;
}
for文でも、更新処理を書き忘れると無限ループになることがあります。
C#for (int i = 0; i < 10;)
{
Console.WriteLine(i);
}
このコードでは、iが変化しないため、ループが終わりません。
無限ループを防ぐためには、次の点を確認しましょう。
条件式が正しいか
カウンター変数が更新されているか
breakで抜けられる条件があるか
条件に使う変数が意図通り変化しているか
9-4. foreach中にListを変更するとエラーになる理由
foreach文でListをループしている途中に、要素を追加・削除するとエラーになることがあります。
たとえば、次のコードは問題があります。
C#List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
foreach (int number in numbers)
{
if (number % 2 == 0)
{
numbers.Remove(number);
}
}
foreach文は、コレクションの状態を前提に順番に要素を取り出します。その途中でListの内容が変更されると、正しくループを続けられなくなるため、例外が発生します。
Listから要素を削除したい場合は、後ろからfor文で処理する方法があります。
C#List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}
後ろから削除すれば、まだ処理していない要素のインデックスがずれにくくなります。
また、条件に合う要素だけを残すなら、LINQのWhereを使う方法もあります。
C#numbers = numbers.Where(number => number % 2 != 0).ToList();
foreach中にListを変更しない、という点は重要です。
9-5. nullのコレクションをループするときの注意点
C#では、コレクションがnullの状態でforeachしようとするとエラーになります。
C#List<string> names = null;
foreach (string name in names)
{
Console.WriteLine(name);
}
このコードは、namesがnullなので例外が発生します。
ループする前にnullチェックを行いましょう。
C#List<string> names = null;
if (names != null)
{
foreach (string name in names)
{
Console.WriteLine(name);
}
}
また、空のListで初期化しておく方法もあります。
C#List<string> names = new List<string>();
foreach (string name in names)
{
Console.WriteLine(name);
}
空のListであれば、foreach文は1回も実行されず、エラーにもなりません。
nullの可能性があるコレクションを扱う場合は、次のようにnull合体演算子を使うこともあります。
C#foreach (string name in names ?? new List<string>())
{
Console.WriteLine(name);
}
ただし、初心者のうちは、まずnullチェックを明示的に書くと理解しやすいです。
9-6. ループのネストが深くなりすぎる問題
ループの中にループを書くことをネストと呼びます。
2重ループ程度であればよく使われます。
C#for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.WriteLine($"{i}, {j}");
}
}
しかし、ネストが深くなりすぎると、コードが読みにくくなります。
C#foreach (var user in users)
{
foreach (var order in user.Orders)
{
foreach (var item in order.Items)
{
foreach (var option in item.Options)
{
Console.WriteLine(option.Name);
}
}
}
}
このようなコードは、どの処理が何をしているのか追いにくくなります。
対策としては、処理をメソッドに分ける方法があります。
C#foreach (var user in users)
{
PrintUserOptions(user);
}
C#static void PrintUserOptions(User user)
{
foreach (var order in user.Orders)
{
foreach (var item in order.Items)
{
foreach (var option in item.Options)
{
Console.WriteLine(option.Name);
}
}
}
}
さらに分割できる場合は、より小さなメソッドに分けると読みやすくなります。
ループのネストが深いときは、「処理を分けられないか」を考えましょう。
10. C#のloopをより読みやすく書くコツ
C#のloopは、ただ動けばよいわけではありません。
実際の開発では、自分だけでなく他の人が読むこともあります。また、数週間後や数か月後の自分が読み返すこともあります。
そのため、読みやすいloopを書くことが大切です。
10-1. 変数名をわかりやすくする
短いfor文では、カウンター変数にiを使うことがよくあります。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
これは問題ありません。
しかし、foreach文では、要素の意味がわかる変数名を使うと読みやすくなります。
悪い例です。
C#foreach (var x in users)
{
Console.WriteLine(x.Name);
}
xが何を表しているのか、少しわかりにくいです。
良い例です。
C#foreach (var user in users)
{
Console.WriteLine(user.Name);
}
変数名をuserにすることで、usersの中から1人のユーザーを取り出していることがわかります。
Listがscoresなら、要素はscoreにすると自然です。
C#foreach (int score in scores)
{
Console.WriteLine(score);
}
コレクション名は複数形、要素名は単数形にすると、読みやすいコードになります。
10-2. ループ内の処理を短くする
ループ内の処理が長くなると、何を繰り返しているのか理解しにくくなります。
C#foreach (var order in orders)
{
// 入力チェック
// 金額計算
// 割引計算
// 在庫確認
// メール送信
// ログ出力
}
このように、ループ内に多くの処理が詰め込まれていると、コードが複雑になります。
処理をメソッドに分けると読みやすくなります。
C#foreach (var order in orders)
{
ProcessOrder(order);
}
C#static void ProcessOrder(Order order)
{
// 注文処理
}
ループを見るだけで、「各注文を処理している」とわかるようになります。
ループ内の処理は、できるだけ短く、目的がはっきりわかるように書きましょう。
10-3. 条件式をシンプルにする
ループの条件式が複雑すぎると、コードが読みにくくなります。
悪い例です。
C#while (user != null && user.IsActive && !user.IsDeleted && retryCount < 3 && DateTime.Now < limitTime)
{
// 処理
}
条件が多く、何を基準にループしているのか理解しにくいです。
このような場合は、条件を変数に分けると読みやすくなります。
C#bool canRetry = retryCount < 3;
bool isUserValid = user != null && user.IsActive && !user.IsDeleted;
bool isWithinLimit = DateTime.Now < limitTime;
while (isUserValid && canRetry && isWithinLimit)
{
// 処理
canRetry = retryCount < 3;
isWithinLimit = DateTime.Now < limitTime;
}
また、条件判定をメソッドにする方法もあります。
C#while (CanContinue(user, retryCount, limitTime))
{
// 処理
}
条件式は、できるだけ「何を判断しているのか」がわかる形にしましょう。
10-4. 必要に応じてメソッド化する
ループ内の処理が複雑になったら、メソッド化を検討しましょう。
たとえば、ユーザー一覧を処理するコードがあるとします。
C#foreach (var user in users)
{
if (user.IsActive)
{
string message = $"こんにちは、{user.Name}さん";
Console.WriteLine(message);
}
}
これくらいなら問題ありません。
しかし、処理が増えてきたら、メソッドに分けたほうが読みやすくなります。
C#foreach (var user in users)
{
PrintGreetingIfActive(user);
}
C#static void PrintGreetingIfActive(User user)
{
if (!user.IsActive)
{
return;
}
string message = $"こんにちは、{user.Name}さん";
Console.WriteLine(message);
}
メソッド化すると、ループ側のコードがすっきりします。
C#foreach (var user in users)
{
PrintGreetingIfActive(user);
}
このように、loopの中で「何をしているか」が一目でわかるようになります。
10-5. LINQで置き換えられるケースを知る
C#では、loopで書ける処理の一部をLINQで置き換えることができます。
たとえば、Listの中から60点以上の点数だけ取り出す処理をforeachで書くと、次のようになります。
C#List<int> scores = new List<int> { 80, 45, 90, 30, 70 };
List<int> passedScores = new List<int>();
foreach (int score in scores)
{
if (score >= 60)
{
passedScores.Add(score);
}
}
LINQを使うと、次のように書けます。
C#List<int> passedScores = scores.Where(score => score >= 60).ToList();
合計値を求める場合も、foreachで書けます。
C#int total = 0;
foreach (int score in scores)
{
total += score;
}
LINQでは次のように書けます。
C#int total = scores.Sum();
ただし、初心者のうちは、まずloopで処理の流れを理解することが大切です。
LINQは便利ですが、複雑に使いすぎると逆に読みにくくなることもあります。
10-6. パフォーマンスより可読性を優先すべき場面
C#のloopでは、パフォーマンスを気にする場面もあります。しかし、初心者のうちは、まず可読性を優先することが大切です。
たとえば、配列の全要素を表示するだけなら、for文でもforeach文でも大きな違いを気にする必要はほとんどありません。
C#foreach (string name in names)
{
Console.WriteLine(name);
}
このコードはシンプルで読みやすいです。
無理にfor文へ置き換えても、読みやすさが下がる場合があります。
C#for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}
インデックスが不要なら、foreach文のほうが自然です。
もちろん、大量データを処理する場合や、処理速度が重要な場面では、パフォーマンスを意識する必要があります。
しかし、通常の業務アプリケーションや学習段階では、まず次のことを優先しましょう。
何をしているかがわかりやすい
バグが入りにくい
修正しやすい
他の人が読んでも理解しやすい
読みやすいloopを書くことは、結果的に保守しやすいコードにつながります。
11. C#のloopに関するよくある質問
ここでは、C#のloopについて初心者が疑問に思いやすいポイントをQ&A形式で解説します。
11-1. C#でloopとforは同じ意味ですか?
厳密には同じ意味ではありません。
loopは「繰り返し処理」全体を指す言葉です。一方、forはC#で使えるループ構文の1つです。
C#のloopには、主に次の種類があります。
C#for
foreach
while
do while
つまり、forはloopの一種です。
loopという大きな分類の中に、for文やforeach文、while文がある
と考えるとわかりやすいです。
11-2. forとforeachはどちらを使うべきですか?
インデックス番号が必要ならfor文、不要ならforeach文を使うのが基本です。
配列やListの要素を順番に処理するだけなら、foreach文が読みやすいです。
C#foreach (string name in names)
{
Console.WriteLine(name);
}
一方、何番目の要素かを使いたい場合は、for文が向いています。
C#for (int i = 0; i < names.Count; i++)
{
Console.WriteLine($"{i}: {names[i]}");
}
また、逆順に処理したい場合や、2つ飛ばしで処理したい場合もfor文が便利です。
C#for (int i = names.Count - 1; i >= 0; i--)
{
Console.WriteLine(names[i]);
}
迷ったときは、まず「インデックスが必要か」を考えましょう。
11-3. while文はどんなときに使いますか?
while文は、繰り返す回数が事前に決まっていないときに使います。
たとえば、ユーザーが特定の文字を入力するまで処理を続ける場合です。
C#string input = "";
while (input != "exit")
{
Console.Write("入力してください: ");
input = Console.ReadLine();
}
この処理は、ユーザーが何回入力するかわかりません。そのため、for文よりwhile文が向いています。
while文を使う代表的な場面は次のとおりです。
ユーザー入力を繰り返す
条件を満たすまで待つ
成功するまで再試行する
ゲームやアプリの状態が続く間だけ処理する
回数ではなく条件で繰り返す場合は、while文を使うと覚えておきましょう。
11-4. foreachで要素を削除できますか?
基本的に、foreachでループしている最中にListの要素を削除するのは避けるべきです。
次のようなコードは、例外が発生する可能性があります。
C#foreach (int number in numbers)
{
if (number % 2 == 0)
{
numbers.Remove(number);
}
}
Listの要素を削除したい場合は、for文で後ろから処理する方法があります。
C#for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}
また、条件に合う要素だけを残す場合は、LINQを使う方法もあります。
C#numbers = numbers.Where(number => number % 2 != 0).ToList();
foreachは、基本的には読み取り用として使うと安全です。
11-5. ループを途中で止めるにはどうすればいいですか?
ループを途中で止めたい場合は、breakを使います。
C#for (int i = 0; i < 10; i++)
{
if (i == 5)
{
break;
}
Console.WriteLine(i);
}
実行結果は次のとおりです。
0
1
2
3
4
i == 5になった時点で、ループが終了します。
foreach文でもbreakは使えます。
C#foreach (string name in names)
{
if (name == "田中")
{
Console.WriteLine("見つかりました");
break;
}
}
特定の条件になったら、それ以上ループを続ける必要がない場合にbreakを使いましょう。
11-6. C#で無限ループを書くにはどうすればいいですか?
C#で無限ループを書く場合は、while (true)を使うことが多いです。
C#while (true)
{
Console.WriteLine("処理中");
break;
}
ただし、この例ではbreakがあるため、実際には1回で終了します。
ユーザーがexitと入力するまで続ける例は次のとおりです。
C#while (true)
{
Console.Write("入力してください。終了するには exit: ");
string input = Console.ReadLine();
if (input == "exit")
{
break;
}
Console.WriteLine($"入力内容: {input}");
}
無限ループを書く場合は、必ず終了条件を用意しましょう。
for文でも無限ループは書けます。
C#for (;;)
{
Console.WriteLine("無限ループ");
}
ただし、初心者のうちはwhile (true)のほうが意図を理解しやすいです。
無限ループは便利な場面もありますが、終了条件がないとプログラムが止まらなくなるため注意が必要です。
まとめ
C#のloopは、同じ処理を繰り返し実行するための重要な仕組みです。
C#では、主に次のループ構文を使います。
C#for
foreach
while
do while
それぞれの使い分けは、次のように考えるとわかりやすいです。
for :回数が決まっている繰り返しに使う
foreach :配列やListなどの要素を順番に処理する
while :条件を満たす間だけ繰り返す
do while :最低1回は実行したいときに使う
配列やListの要素をすべて処理するだけなら、foreach文が読みやすいです。
C#foreach (var item in items)
{
Console.WriteLine(item);
}
インデックスが必要な場合や、回数を指定したい場合はfor文が向いています。
C#for (int i = 0; i < items.Count; i++)
{
Console.WriteLine(items[i]);
}
条件によって繰り返す場合はwhile文を使います。
C#while (condition)
{
// 条件が true の間だけ繰り返す
}
最低1回は実行したい場合はdo while文を使います。
C#do
{
// 最低1回は実行する
}
while (condition);
また、ループの途中で終了したい場合はbreak、今回の処理だけスキップしたい場合はcontinue、メソッドごと終了したい場合はreturnを使います。
C#のloopを使いこなすためには、文法を覚えるだけでなく、「どのループを使うと読みやすいか」を考えることが大切です。
初心者のうちは、まず次の基準で選ぶとよいでしょう。
全要素を処理するならforeach
回数やインデックスが必要ならfor
条件で続けるならwhile
最低1回実行するならdo while
この基本を押さえておけば、C#の繰り返し処理を無理なく書けるようになります。

