C#の無限ループとは?while(true)・for(;;)の書き方、抜け出し方、注意点を初心者向けに解説
はじめに
C#で繰り返し処理を学んでいると、「無限ループ」という言葉を目にすることがあります。
無限ループとは、名前のとおり終了せずに繰り返し続けるループ処理のことです。初心者にとっては「バグでプログラムが止まらなくなる危険なもの」というイメージが強いかもしれません。
しかし、C#の無限ループは必ずしも悪いものではありません。たとえば、ユーザーが終了を選ぶまでメニューを表示し続ける処理や、サーバーのように常に動き続ける処理では、意図的に無限ループを使うことがあります。
この記事では、C#の無限ループについて、while(true)やfor(;;)の書き方、breakやreturnによる抜け出し方、初心者が注意すべきポイントまでわかりやすく解説します。
1. C#の無限ループとは?
1-1. 無限ループの意味
C#の無限ループとは、終了条件が満たされず、処理がずっと繰り返されるループのことです。
たとえば、次のようなコードは無限ループになります。
C#while (true)
{
Console.WriteLine("繰り返し実行されます");
}
while文は、条件式がtrueの間、処理を繰り返します。
この例では条件式に直接trueを指定しているため、条件が常に真になります。そのため、何もしなければループは終了しません。
無限ループは、以下のようなループ文で発生します。
C#while (true)
{
}
for (;;)
{
}
do
{
} while (true);
特によく使われるのは、while(true)とfor(;;)です。
1-2. 意図的な無限ループとバグによる無限ループの違い
無限ループには、大きく分けて2種類あります。
1つ目は、意図的に書く無限ループです。
たとえば、ユーザーが「終了」を選ぶまでメニューを表示し続ける処理です。
C#while (true)
{
Console.WriteLine("1: 続ける");
Console.WriteLine("2: 終了");
string input = Console.ReadLine();
if (input == "2")
{
break;
}
}
このコードは一見すると無限ループですが、ユーザーが2を入力するとbreakで終了します。
つまり、「基本的には繰り返し続けるが、特定の条件で抜ける」という設計です。
一方、バグによる無限ループは、意図せず処理が終わらなくなっている状態です。
C#int count = 0;
while (count < 5)
{
Console.WriteLine(count);
// count++ を書き忘れている
}
このコードでは、countの値がずっと0のままなので、count < 5が常にtrueになります。その結果、ループが終わりません。
意図的な無限ループには終了条件がありますが、バグによる無限ループには正しい終了条件がない、または終了条件が機能していないという違いがあります。
1-3. C#で無限ループが起きる主な原因
C#で無限ループが起きる主な原因は、次のようなものです。
C#int i = 0;
while (i < 10)
{
Console.WriteLine(i);
}
この例では、iを増やす処理がないため、i < 10がずっとtrueのままです。
また、終了条件の書き方を間違えて無限ループになることもあります。
C#int i = 10;
while (i > 0)
{
Console.WriteLine(i);
i++;
}
このコードでは、iを減らすべきところで増やしているため、i > 0の条件がいつまでも成立してしまいます。
ほかにも、次のような原因で無限ループが発生します。
カウンター変数を更新し忘れる
条件式が常に
trueになるbreakを書く場所を間違えるユーザー入力の終了判定が間違っている
コレクションを処理中に変更してループが終わらない
非同期処理や監視処理でキャンセル手段がない
無限ループを防ぐには、「どの条件で終わるのか」を先に決めてからコードを書くことが大切です。
2. C#で無限ループを書く基本構文
2-1. while(true)で書く無限ループ
C#で無限ループを書く代表的な方法が、while(true)です。
C#while (true)
{
Console.WriteLine("無限ループ中です");
}
while文は、条件式がtrueの間、ブロック内の処理を繰り返します。
while(true)は条件式が常にtrueなので、そのままでは終了しません。
実際に使う場合は、通常はbreakなどで抜け出す条件を書きます。
C#while (true)
{
string input = Console.ReadLine();
if (input == "exit")
{
break;
}
Console.WriteLine("入力内容: " + input);
}
このように、while(true)は「いつ終わるかをループの中で判断したい場合」によく使われます。
2-2. for(;;)で書く無限ループ
C#では、for(;;)でも無限ループを書くことができます。
C#for (;;)
{
Console.WriteLine("無限ループ中です");
}
通常のfor文は、次のように書きます。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
for文の丸かっこの中には、次の3つの要素があります。
C#for (初期化式; 条件式; 更新式)
{
}
しかし、C#ではこれらを省略できます。
C#for (;;)
{
}
条件式を省略すると、条件が常に成立するものとして扱われるため、無限ループになります。
2-3. while(true)とfor(;;)の違い
while(true)とfor(;;)は、どちらも無限ループを作ることができます。
動作としては、どちらも「明示的に抜けるまで繰り返す」という点でほぼ同じです。
C#while (true)
{
// 繰り返す処理
}
C#for (;;)
{
// 繰り返す処理
}
違いは、主に見た目と意味の伝わりやすさです。
while(true)は、「trueの間ずっと繰り返す」という意味が直感的にわかりやすい書き方です。
一方、for(;;)は短く書けますが、初心者には少し読みづらく感じることがあります。
また、for文は本来、回数が決まっている繰り返しに使われることが多い構文です。そのため、無限ループを意図していることを明確にしたい場合は、while(true)の方が読みやすい場面が多いです。
2-4. 初心者にはどちらの書き方がおすすめか
初心者には、まずwhile(true)をおすすめします。
理由は、コードの意味がわかりやすいからです。
C#while (true)
{
// 条件を満たすまで繰り返す
}
whileは「条件が成り立つ間、繰り返す」という意味なので、while(true)は「常に繰り返す」という意味だと理解しやすいです。
また、次のようにbreakと組み合わせたときも、処理の流れが読みやすくなります。
C#while (true)
{
Console.Write("終了するには q を入力してください: ");
string input = Console.ReadLine();
if (input == "q")
{
break;
}
}
for(;;)はC#のコードとして問題ありませんが、初心者のうちは「なぜこれで無限ループになるのか」がわかりにくい場合があります。
そのため、最初はwhile(true)を使い、慣れてきたらfor(;;)も読めるようにしておくとよいでしょう。
3. while(true)を使った無限ループの書き方
3-1. while(true)の基本コード
while(true)を使った無限ループの基本形は次のとおりです。
C#while (true)
{
// 繰り返したい処理
}
たとえば、コンソールに文字を出力し続ける場合は次のように書きます。
C#while (true)
{
Console.WriteLine("処理を実行しています");
}
ただし、このコードは止まらずに文字を出力し続けます。
実際のプログラムでは、無限ループの中に終了条件を書くのが基本です。
C#while (true)
{
Console.WriteLine("処理を実行しています");
if (/* 終了条件 */)
{
break;
}
}
無限ループを書くときは、while(true)そのものよりも、「どこで抜けるか」を意識することが重要です。
3-2. 条件を満たしたらbreakで抜ける書き方
無限ループから抜け出す代表的な方法がbreakです。
breakを使うと、その時点でループ処理を終了できます。
C#int count = 0;
while (true)
{
Console.WriteLine(count);
if (count >= 5)
{
break;
}
count++;
}
このコードでは、countが5以上になったらbreakでループを終了します。
実行すると、次のような流れになります。
0
1
2
3
4
5
while(true)は条件が常にtrueですが、ループの中でbreakを実行すれば終了できます。
よく使われる形は次のようなコードです。
C#while (true)
{
// 処理
if (終了したい条件)
{
break;
}
}
この形を覚えておくと、ユーザー入力やメニュー処理などに応用できます。
3-3. ユーザー入力を待ち続けるサンプル
while(true)は、ユーザー入力を待ち続ける処理でよく使われます。
次の例では、ユーザーがexitと入力するまで入力を受け付け続けます。
C#while (true)
{
Console.Write("文字を入力してください(exitで終了): ");
string input = Console.ReadLine();
if (input == "exit")
{
Console.WriteLine("終了します");
break;
}
Console.WriteLine("入力された文字: " + input);
}
このコードでは、毎回ユーザーの入力を受け取り、exitかどうかを判定しています。
exitでなければ入力内容を表示し、再び入力待ちに戻ります。
このような処理は、コンソールアプリでよく使われます。
たとえば、次のような場面です。
コマンド入力を受け付ける
メニューを表示し続ける
ユーザーが正しい値を入力するまで待つ
終了コマンドが入力されるまで処理を続ける
ユーザーの操作によって終了する処理では、while(true)とbreakの組み合わせが使いやすいです。
3-4. カウンターを使って終了条件を作るサンプル
無限ループでも、カウンターを使えば安全に終了条件を作れます。
C#int count = 0;
while (true)
{
Console.WriteLine("現在の回数: " + count);
count++;
if (count >= 5)
{
break;
}
}
このコードでは、countを1ずつ増やし、5以上になったらループを終了します。
ポイントは、カウンターを必ず更新することです。
C#count++;
この更新処理を書き忘れると、終了条件に到達できず、無限ループになってしまいます。
悪い例は次のとおりです。
C#int count = 0;
while (true)
{
Console.WriteLine("現在の回数: " + count);
if (count >= 5)
{
break;
}
}
このコードでは、countがずっと0のままなので、count >= 5になりません。
カウンターを使う場合は、次の3点を確認しましょう。
初期値が正しいか
更新処理を書いているか
終了条件に到達できるか
4. for(;;)を使った無限ループの書き方
4-1. for(;;)の基本コード
for(;;)を使った無限ループの基本形は次のとおりです。
C#for (;;)
{
// 繰り返したい処理
}
たとえば、次のコードは無限にメッセージを表示します。
C#for (;;)
{
Console.WriteLine("処理を実行しています");
}
for(;;)は、見た目は少し特殊ですが、C#では正しい書き方です。
ただし、実際に使う場合は、breakなどで終了できるようにします。
C#for (;;)
{
Console.Write("終了するには end と入力してください: ");
string input = Console.ReadLine();
if (input == "end")
{
break;
}
}
for(;;)もwhile(true)と同じように、終了条件をループ内に書いて使います。
4-2. for文の初期化式・条件式・更新式を省略できる理由
通常のfor文は、次のように書きます。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
このfor文には、3つの要素があります。
C#for (初期化式; 条件式; 更新式)
{
}
それぞれの意味は次のとおりです。
初期化式:ループ開始前に一度だけ実行される
条件式:ループを続けるかどうかを判定する
更新式:1回のループが終わるたびに実行される
C#のfor文では、これらを省略できます。
C#for (;;)
{
}
この場合、条件式が省略されています。
条件式がない場合、ループを終了する条件がないため、無限ループとして動作します。
次のコードと似た意味になります。
C#while (true)
{
}
ただし、for(;;)は初心者には意味がわかりにくいことがあるため、チーム開発では読みやすさも意識して使うとよいでしょう。
4-3. for(;;)をbreakで終了するサンプル
for(;;)でも、breakを使えばループから抜け出せます。
C#int count = 0;
for (;;)
{
Console.WriteLine("count = " + count);
if (count >= 3)
{
break;
}
count++;
}
このコードでは、countが3以上になったらbreakで終了します。
実行結果は次のようになります。
count = 0
count = 1
count = 2
count = 3
for(;;)は無限ループですが、breakが実行されるとループは終了します。
ユーザー入力を使った例も見てみましょう。
C#for (;;)
{
Console.Write("コマンドを入力してください(qで終了): ");
string command = Console.ReadLine();
if (command == "q")
{
break;
}
Console.WriteLine("実行したコマンド: " + command);
}
このように、for(;;)もwhile(true)と同じように使えます。
4-4. for(;;)が使われやすい場面
for(;;)は、C#でも無限ループとして使えますが、while(true)ほど初心者向けではありません。
それでも、次のような場面で見かけることがあります。
C言語やC++に近い書き方を好むコード
短く無限ループを書きたい場合
低レベルな処理や常駐処理
ループであることを強く表現したい場合
既存コードのスタイルに合わせる場合
たとえば、常に処理を待ち受けるようなコードでは、次のように書かれることがあります。
C#for (;;)
{
// 監視処理
// 条件を満たしたら break
}
ただし、業務コードや初心者向けのコードでは、読みやすさを優先してwhile(true)を使うことも多いです。
どちらを使う場合でも、終了条件をわかりやすく書くことが大切です。
5. C#の無限ループから抜け出す方法
5-1. breakでループを終了する
無限ループから抜け出す最も基本的な方法は、breakです。
breakは、現在実行中のループを終了します。
C#while (true)
{
Console.WriteLine("ループ中です");
if (DateTime.Now.Second % 10 == 0)
{
break;
}
}
よりわかりやすい例として、ユーザー入力で終了するコードを見てみましょう。
C#while (true)
{
Console.Write("入力してください(endで終了): ");
string input = Console.ReadLine();
if (input == "end")
{
break;
}
Console.WriteLine("入力内容: " + input);
}
breakが実行されると、ループの外に処理が移ります。
C#while (true)
{
if (終了条件)
{
break;
}
}
Console.WriteLine("ループが終了しました");
breakは、「ループだけを終了したい」ときに使います。
5-2. returnでメソッドごと終了する
returnを使うと、ループだけでなく、メソッド全体を終了できます。
C#static void Main()
{
while (true)
{
Console.Write("qで終了: ");
string input = Console.ReadLine();
if (input == "q")
{
return;
}
Console.WriteLine("入力内容: " + input);
}
// returnした場合、ここには到達しない
}
breakとreturnの違いは、終了する範囲です。
breakはループだけを終了します。
C#while (true)
{
break;
}
Console.WriteLine("ここは実行されます");
一方、returnはメソッドを終了します。
C#static void Sample()
{
while (true)
{
return;
}
// ここは実行されない
}
メソッド内の処理を完全に終えたい場合はreturnが便利です。
ただし、ループ後にも実行したい処理がある場合は、returnではなくbreakを使いましょう。
5-3. 条件式をfalseにして終了する
while(true)ではなく、変数を条件式に使ってループを制御する方法もあります。
C#bool isRunning = true;
while (isRunning)
{
Console.Write("終了しますか? y/n: ");
string input = Console.ReadLine();
if (input == "y")
{
isRunning = false;
}
}
このコードでは、isRunningがtrueの間だけループします。
ユーザーがyを入力すると、isRunningがfalseになり、次の条件判定でループが終了します。
この書き方は、終了状態を変数として管理したい場合に便利です。
C#bool shouldContinue = true;
while (shouldContinue)
{
// 処理
if (終了条件)
{
shouldContinue = false;
}
}
breakよりも処理の意図が明確になる場合があります。
ただし、条件変数を更新し忘れると無限ループになるため注意が必要です。
5-4. continueでは無限ループから抜け出せない
continueは、ループを終了する命令ではありません。
continueは、現在の繰り返しをスキップして、次の繰り返しに進む命令です。
C#int count = 0;
while (true)
{
count++;
if (count < 5)
{
continue;
}
break;
}
このコードでは、countが5未満の間はcontinueで次のループに進みます。
countが5以上になるとbreakが実行されます。
注意したいのは、continueだけではループから抜け出せないということです。
次のコードは危険です。
C#int count = 0;
while (true)
{
if (count < 5)
{
continue;
}
count++;
}
このコードでは、count++に到達する前にcontinueされるため、countがずっと0のままになります。
結果として、無限ループになります。
continueを使う場合は、カウンターの更新や終了条件の判定が正しく行われるか確認しましょう。
5-5. Visual Studioやコンソールで実行中の無限ループを止める方法
誤って無限ループを実行してしまった場合は、実行中のプログラムを停止します。
Visual Studioでデバッグ実行している場合は、次の方法で停止できます。
Shift + F5
または、上部メニューやツールバーの「停止」ボタンを押します。
コンソールで実行している場合は、一般的に次のキーで停止できます。
Ctrl + C
Visual Studio CodeのターミナルやWindows Terminal、PowerShellなどでも、Ctrl + Cで実行中のコンソールアプリを中断できることが多いです。
ただし、環境や実行方法によって操作が異なる場合があります。
無限ループで画面が固まったように見える場合でも、まずは慌てずに実行を停止しましょう。
学習中は、無限ループを書く前に次のような安全策を入れると安心です。
C#int count = 0;
while (true)
{
Console.WriteLine(count);
count++;
if (count >= 100)
{
break;
}
}
最大回数を決めておくと、誤って止まらない処理になるのを防げます。
6. 無限ループが必要になる実用例
6-1. メニュー画面を表示し続ける処理
コンソールアプリでは、ユーザーが終了を選ぶまでメニューを表示し続ける処理によく無限ループを使います。
C#while (true)
{
Console.WriteLine("=== メニュー ===");
Console.WriteLine("1: あいさつを表示");
Console.WriteLine("2: 現在時刻を表示");
Console.WriteLine("3: 終了");
Console.Write("番号を選んでください: ");
string input = Console.ReadLine();
if (input == "1")
{
Console.WriteLine("こんにちは!");
}
else if (input == "2")
{
Console.WriteLine(DateTime.Now);
}
else if (input == "3")
{
Console.WriteLine("終了します");
break;
}
else
{
Console.WriteLine("正しい番号を入力してください");
}
Console.WriteLine();
}
このようなメニュー処理では、最初から繰り返し回数が決まっていません。
ユーザーが終了を選ぶまで続けたいので、while(true)が適しています。
6-2. 入力値が正しくなるまで繰り返す処理
ユーザーが正しい値を入力するまで繰り返す処理にも、無限ループが使えます。
C#int age;
while (true)
{
Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();
if (int.TryParse(input, out age) && age >= 0)
{
break;
}
Console.WriteLine("0以上の整数を入力してください");
}
Console.WriteLine("入力された年齢: " + age);
このコードでは、入力値が整数かつ0以上であればbreakでループを抜けます。
正しくない入力の場合は、エラーメッセージを表示して再入力を求めます。
このような「正しい入力があるまで繰り返す」処理は、実用的な無限ループの代表例です。
6-3. サーバーや監視処理のように常時動かす処理
サーバーや監視プログラムでは、常に処理を続ける必要があります。
たとえば、一定間隔で状態を確認する処理は次のように書けます。
C#while (true)
{
Console.WriteLine("状態を確認しています: " + DateTime.Now);
Thread.Sleep(1000);
}
このコードは、1秒ごとに状態確認のメッセージを表示します。
ただし、実際のアプリケーションでは、ただのwhile(true)ではなく、終了要求を受け取れるようにすることが重要です。
C#bool isRunning = true;
while (isRunning)
{
Console.WriteLine("監視中です");
// 何らかの条件で終了
if (Console.KeyAvailable)
{
isRunning = false;
}
Thread.Sleep(1000);
}
常時動かす処理では、CPUを使いすぎないように待機時間を入れることも大切です。
6-4. ゲームループで使う処理
ゲームでは、画面の更新や入力処理を繰り返す「ゲームループ」が使われます。
イメージとしては次のような処理です。
C#while (true)
{
// 入力を受け取る
// キャラクターや敵の状態を更新する
// 画面を描画する
if (/* ゲーム終了条件 */)
{
break;
}
}
ゲームは、プレイヤーが終了するまで動き続ける必要があります。
そのため、無限ループに近い構造で処理を回し続けます。
実際のゲーム開発では、Unityなどのゲームエンジンが更新処理の仕組みを提供してくれるため、自分でwhile(true)を書く場面は多くありません。
たとえばUnityでは、Updateメソッドが毎フレーム呼び出されます。
C#void Update()
{
// 毎フレーム実行したい処理
}
考え方としては、ゲームループも「終了するまで繰り返し続ける処理」の一種です。
7. バグで無限ループになりやすいパターン
7-1. カウンター変数を更新し忘れる
初心者がよくやるミスの1つが、カウンター変数の更新忘れです。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
}
このコードでは、iがずっと0のままです。
そのため、i < 5が常にtrueになり、ループが終わりません。
正しくは、ループ内でiを更新します。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
i++;
}
for文では更新式を書く場所が決まっているため、このミスは比較的起こりにくいです。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
回数が決まっている繰り返しでは、for文を使うと安全です。
7-2. 終了条件の書き方を間違える
終了条件の比較演算子を間違えると、無限ループになることがあります。
C#int i = 0;
while (i >= 0)
{
Console.WriteLine(i);
i++;
}
このコードでは、iは0から増え続けます。
そのため、i >= 0はずっとtrueになり、ループが終わりません。
本来、5回だけ繰り返したいなら次のように書きます。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
i++;
}
また、値を減らす場合は条件と更新の向きに注意が必要です。
C#int i = 5;
while (i > 0)
{
Console.WriteLine(i);
i--;
}
条件式を書くときは、次の点を確認しましょう。
変数は終了条件に近づいているか
比較演算子の向きは正しいか
境界値に問題はないか
条件が永遠に
trueにならないか
7-3. breakを書く位置を間違える
breakを書いていても、位置が間違っていると期待どおりに終了しないことがあります。
C#while (true)
{
Console.Write("入力してください: ");
string input = Console.ReadLine();
Console.WriteLine("処理を続けます");
if (input == "end")
{
break;
}
}
このコードでは、endと入力しても、breakの前にConsole.WriteLine("処理を続けます")が実行されます。
大きな問題ではない場合もありますが、終了判定は早めに書いた方が自然です。
C#while (true)
{
Console.Write("入力してください: ");
string input = Console.ReadLine();
if (input == "end")
{
break;
}
Console.WriteLine("処理を続けます");
}
また、ネストしたループでは、breakがどのループを抜けるのかにも注意が必要です。
C#while (true)
{
for (int i = 0; i < 3; i++)
{
if (i == 1)
{
break;
}
}
// while(true)は続く
}
この例のbreakは内側のfor文だけを終了します。外側のwhile(true)は終了しません。
外側のループも終了したい場合は、フラグ変数を使うなどの工夫が必要です。
C#bool isRunning = true;
while (isRunning)
{
for (int i = 0; i < 3; i++)
{
if (i == 1)
{
isRunning = false;
break;
}
}
}
7-4. while文の条件が常にtrueになっている
while文の条件が常にtrueになる書き方にも注意が必要です。
C#int number = 10;
while (number > 0 || number < 100)
{
Console.WriteLine(number);
number++;
}
この条件式は、一見すると「0より大きく100より小さい間」のように見えるかもしれません。
しかし、||は「または」という意味です。
number > 0またはnumber < 100のどちらかが成立すればtrueになります。
多くの場合、この条件は意図せず長く成立し続けます。
本当に「0より大きく100より小さい間」にしたいなら、&&を使います。
C#int number = 10;
while (number > 0 && number < 100)
{
Console.WriteLine(number);
number++;
}
条件式では、&&と||の使い分けが重要です。
&&:かつ||:または
終了条件が複雑になるほど、意図しない無限ループが起きやすくなります。
7-5. コレクションをループ中に変更して処理が終わらない
リストなどのコレクションを処理しているときに、ループ中で要素を追加し続けると、処理が終わらなくなることがあります。
C#List<int> numbers = new List<int> { 1, 2, 3 };
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine(numbers[i]);
numbers.Add(i);
}
このコードでは、ループのたびにnumbers.Countが増えます。
iも増えますが、リストの件数も増え続けるため、終了しない可能性があります。
コレクションを処理するときは、ループ中に要素数が変わるかどうかに注意しましょう。
安全に処理したい場合は、最初の件数を変数に保存しておく方法があります。
C#List<int> numbers = new List<int> { 1, 2, 3 };
int count = numbers.Count;
for (int i = 0; i < count; i++)
{
Console.WriteLine(numbers[i]);
numbers.Add(i);
}
このコードでは、最初の件数だけ処理するため、ループが終わります。
コレクションをループ中に変更する場合は、処理対象の範囲を明確にすることが大切です。
8. C#で無限ループを書くときの注意点
8-1. CPU使用率が高くなる可能性がある
無限ループの中で待機時間を入れずに処理を繰り返すと、CPU使用率が高くなることがあります。
C#while (true)
{
// 何もしない
}
このようなコードは、CPUが全力でループを回し続けます。
画面上は何も起きていないように見えても、内部では高速に処理が繰り返されています。
定期的に処理すればよい場合は、Thread.Sleepなどで待機時間を入れます。
C#while (true)
{
Console.WriteLine("処理中");
Thread.Sleep(1000);
}
この例では、1秒ごとに処理が実行されます。
無限ループを書くときは、「本当に休みなく処理を回す必要があるか」を考えましょう。
8-2. プログラムが固まったように見えることがある
無限ループの書き方によっては、プログラムが固まったように見えることがあります。
特に、画面更新やユーザー操作を受け付けるスレッドで重いループ処理を実行すると、アプリケーションが応答しなくなる場合があります。
たとえば、GUIアプリでメインスレッドを占有するようなループを書くと、ボタン操作や画面描画が止まることがあります。
コンソールアプリでも、終了条件がないループを書くと、操作できないように感じることがあります。
C#while (true)
{
Console.WriteLine("止まりません");
}
学習中にこのような状態になったら、Visual StudioならShift + F5、コンソールならCtrl + Cで停止します。
実用的なコードでは、ユーザーがキャンセルできる仕組みや終了条件を必ず用意しましょう。
8-3. 必ず終了条件を設計してから書く
無限ループを書くときは、先に終了条件を決めることが重要です。
たとえば、次のように考えてからコードを書きます。
ユーザーが
qを入力したら終了するカウンターが100になったら終了する
エラーが発生したら終了する
キャンセル要求が来たら終了する
処理対象がなくなったら終了する
終了条件を決めずにwhile(true)を書くと、あとから抜け出し方がわかりにくくなります。
よい例は次のとおりです。
C#while (true)
{
Console.Write("qで終了: ");
string input = Console.ReadLine();
if (input == "q")
{
break;
}
Console.WriteLine("処理を続けます");
}
このコードでは、終了条件が明確です。
無限ループを書くときは、次のように考えると安全です。
何を繰り返すのか
いつ終了するのか
終了したあと何をするのか
この3つを決めてからコードを書きましょう。
8-4. Thread.SleepやTask.Delayで待機時間を入れるべきケース
常に処理し続ける必要がない場合は、ループの中に待機時間を入れるべきです。
同期処理では、Thread.Sleepを使えます。
C#while (true)
{
Console.WriteLine("1秒ごとに実行します");
Thread.Sleep(1000);
}
Thread.Sleep(1000)は、現在のスレッドを1000ミリ秒、つまり1秒停止します。
一方、非同期処理ではTask.Delayを使います。
C#while (true)
{
Console.WriteLine("1秒ごとに実行します");
await Task.Delay(1000);
}
Task.Delayは非同期的に待機できるため、非同期メソッドの中で使いやすいです。
C#static async Task Main()
{
while (true)
{
Console.WriteLine(DateTime.Now);
await Task.Delay(1000);
}
}
ただし、Thread.SleepやTask.Delayを入れれば何でも安全というわけではありません。
終了条件やキャンセル手段もあわせて設計する必要があります。
8-5. 非同期処理ではCancellationTokenでキャンセルできるようにする
非同期処理で無限ループを書く場合は、CancellationTokenを使ってキャンセルできるようにするのが望ましいです。
C#static async Task WatchAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("監視中です");
await Task.Delay(1000, cancellationToken);
}
}
このコードでは、キャンセルが要求されるまで処理を繰り返します。
while(true)ではなく、次のようにキャンセル状態を条件にしています。
C#while (!cancellationToken.IsCancellationRequested)
また、Task.DelayにもcancellationTokenを渡しています。
これにより、待機中でもキャンセルしやすくなります。
使い方の例は次のとおりです。
C#using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using CancellationTokenSource cts = new CancellationTokenSource();
Task task = WatchAsync(cts.Token);
Console.WriteLine("Enterキーで停止します");
Console.ReadLine();
cts.Cancel();
try
{
await task;
}
catch (TaskCanceledException)
{
Console.WriteLine("キャンセルされました");
}
}
static async Task WatchAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("監視中です");
await Task.Delay(1000, cancellationToken);
}
}
}
非同期処理や長時間動く処理では、「外部から止められる設計」にしておくことが大切です。
9. 初心者向け:安全な無限ループの書き方
9-1. 先に終了条件を決める
初心者が無限ループを書くときは、最初に終了条件を決めましょう。
たとえば、次のように決めてからコードを書きます。
ユーザーが q を入力したら終了する
そのうえで、コードにします。
C#while (true)
{
Console.Write("qで終了: ");
string input = Console.ReadLine();
if (input == "q")
{
break;
}
Console.WriteLine("続行します");
}
無限ループは、終了条件がないと危険です。
「何をしたら終わるのか」が説明できない状態でwhile(true)を書かないようにしましょう。
9-2. break条件をループの分かりやすい場所に書く
breakの条件は、できるだけわかりやすい場所に書くのがおすすめです。
特に、ユーザー入力で終了する場合は、入力直後に終了判定を書くと読みやすくなります。
C#while (true)
{
Console.Write("コマンド: ");
string command = Console.ReadLine();
if (command == "exit")
{
break;
}
Console.WriteLine(command + " を実行します");
}
終了条件が処理の奥にあると、どこでループが終わるのかわかりにくくなります。
悪い例は次のとおりです。
C#while (true)
{
Console.Write("コマンド: ");
string command = Console.ReadLine();
Console.WriteLine("処理を開始します");
if (command == "exit")
{
break;
}
}
このコードでは、exitを入力しても「処理を開始します」と表示されてから終了します。
終了判定は、できるだけ自然なタイミングで書きましょう。
9-3. ログやConsole.WriteLineで動作を確認する
無限ループが正しく動いているか確認するには、Console.WriteLineで現在の状態を表示するとわかりやすいです。
C#int count = 0;
while (true)
{
Console.WriteLine("count = " + count);
count++;
if (count >= 5)
{
Console.WriteLine("ループを終了します");
break;
}
}
このように表示しておくと、変数が正しく更新されているか確認できます。
無限ループでよくある問題は、「変数が思ったように変わっていない」ことです。
たとえば、次のように出力すれば、終了条件に近づいているか確認できます。
C#Console.WriteLine("現在の値: " + value);
学習中は、少し多めにログを出して処理の流れを確認するとよいでしょう。
ただし、無限ループの中で大量にConsole.WriteLineを実行すると、出力が非常に多くなるので注意してください。
9-4. 無限ループが不要なら通常のwhile文やfor文を使う
無限ループは便利ですが、必要がない場合は通常のwhile文やfor文を使いましょう。
回数が決まっている場合は、for文が向いています。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
条件が決まっている場合は、通常のwhile文が使えます。
C#int count = 0;
while (count < 5)
{
Console.WriteLine(count);
count++;
}
無限ループを使うべきなのは、主に次のような場合です。
終了タイミングがループの中で決まる
ユーザーの入力によって終了する
常に監視し続ける必要がある
メニューを表示し続ける
キャンセルされるまで処理を続ける
「何回繰り返すか」が最初からわかっているなら、無理にwhile(true)を使う必要はありません。
読みやすく、安全なコードを優先しましょう。
10. C#の無限ループに関するよくある質問
10-1. while(true)は使っても問題ない?
while(true)は使っても問題ありません。
C#でも一般的に使われる書き方です。
ただし、必ず終了条件を用意することが大切です。
C#while (true)
{
string input = Console.ReadLine();
if (input == "exit")
{
break;
}
}
このように、breakなどで抜け出せる設計になっていれば問題ありません。
逆に、終了条件がないwhile(true)は危険です。
C#while (true)
{
Console.WriteLine("止まりません");
}
学習中は、最大回数や終了コマンドを用意しておくと安心です。
10-2. while(true)とwhile(1)は同じ?
C#では、while(true)とwhile(1)は同じではありません。
C#のwhile文の条件式には、bool型の値が必要です。
そのため、次のコードは正しいです。
C#while (true)
{
}
一方、次のコードはC#ではエラーになります。
C#while (1)
{
}
C言語などでは1を真として扱える場合がありますが、C#ではint型の1をbool型のtrueとして扱うことはできません。
C#で無限ループを書く場合は、while(true)を使いましょう。
10-3. for(;;)はなぜ無限ループになる?
for(;;)が無限ループになる理由は、for文の条件式が省略されているからです。
通常のfor文は次の形です。
C#for (初期化式; 条件式; 更新式)
{
}
たとえば、次のコードではi < 5が条件式です。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
一方、for(;;)では初期化式、条件式、更新式がすべて省略されています。
C#for (;;)
{
}
条件式がないため、終了判定が行われず、ループが続きます。
そのため、for(;;)は無限ループとして動作します。
実際に使う場合は、breakなどで終了できるようにします。
C#for (;;)
{
string input = Console.ReadLine();
if (input == "end")
{
break;
}
}
10-4. breakとreturnの違いは?
breakとreturnは、どちらも処理を途中で抜けるために使えますが、終了する範囲が違います。
breakはループを終了します。
C#while (true)
{
break;
}
Console.WriteLine("ここは実行されます");
この場合、breakでwhile文を抜けたあと、次の処理が実行されます。
一方、returnはメソッドを終了します。
C#static void Sample()
{
while (true)
{
return;
}
// ここは実行されない
}
returnが実行されると、そのメソッド自体が終了します。
使い分けは次のように考えるとわかりやすいです。
ループだけを抜けたいなら
breakメソッド全体を終了したいなら
return
ループ後に後処理がある場合は、breakを使うことが多いです。
C#while (true)
{
if (終了条件)
{
break;
}
}
Console.WriteLine("後処理を実行します");
10-5. 無限ループでパソコンが壊れることはある?
通常、C#の無限ループだけでパソコンが物理的に壊れることはほとんどありません。
ただし、CPU使用率が高くなったり、ファンが回ったり、パソコンの動作が重くなったりすることはあります。
特に、待機時間のない無限ループはCPUに負荷をかけます。
C#while (true)
{
}
このようなコードは避けるべきです。
一定間隔で処理すればよい場合は、待機時間を入れましょう。
C#while (true)
{
Console.WriteLine("処理中");
Thread.Sleep(1000);
}
また、実行中に止まらなくなった場合は、Visual StudioならShift + F5、コンソールならCtrl + Cで停止できます。
無限ループそのものよりも、「終了できない設計」や「CPUを使い続ける処理」が問題になります。
まとめ
C#の無限ループとは、終了条件が満たされるまで、または明示的に停止されるまで繰り返し続けるループ処理です。
代表的な書き方には、while(true)とfor(;;)があります。
C#while (true)
{
// 繰り返す処理
}
C#for (;;)
{
// 繰り返す処理
}
初心者には、意味がわかりやすいwhile(true)がおすすめです。
無限ループを使う場合は、breakやreturn、条件変数などを使って、必ず抜け出す方法を用意しましょう。
C#while (true)
{
string input = Console.ReadLine();
if (input == "exit")
{
break;
}
}
また、continueはループを終了する命令ではないため、無限ループから抜ける目的では使えません。
無限ループは、メニュー画面、入力チェック、監視処理、サーバー処理、ゲームループなど、実用的な場面でも使われます。
一方で、カウンターの更新忘れや条件式のミスによって、意図しない無限ループになることもあります。
安全に書くためには、次のポイントを意識しましょう。
先に終了条件を決める
break条件をわかりやすく書くカウンター変数を正しく更新する
必要に応じて
Thread.SleepやTask.Delayを使う非同期処理では
CancellationTokenでキャンセル可能にする無限ループが不要なら通常の
while文やfor文を使う
C#の無限ループは、正しく使えば便利な書き方です。
「なぜ繰り返すのか」「いつ終了するのか」を明確にして、安全で読みやすいコードを書くようにしましょう。

