C#を用いたシステム開発において、同じ処理を何度も繰り返す「ループ処理」は欠かせない要素の一つです。
その中でも 文は、「特定の条件が満たされている間、処理を繰り返す」という非常にシンプルかつ強力な制御構造を持っています。while
配列の要素を順番に処理するだけでなく、ユーザーの入力を待ち続けたり、特定のフラグが書き換わるまで待機したりするなど、その用途は多岐にわたります。
本記事では、C#における 文の基本的な使い方から、実戦で役立つ応用テクニック、さらには while 文との違いや注意点まで、プロの視点で徹底的に解説します。do-while
while文の基本構造と動作原理
C#の 文は、指定した条件式が while である限り、ブロック内のコードを実行し続けるループ機構です。true
まずは、最も基本的な構文を確認しましょう。
while (条件式)
{
// 条件式がtrueの間、繰り返し実行される処理
}
この構造において最も重要な点は、「ループの開始前に条件判定が行われる」という点です。
これを「前判定ループ」と呼びます。
もし最初に条件式を評価した時点で であった場合、ループ内の処理は一度も実行されません。false
基本的なカウントアップの例
具体的なコードを見てみましょう。
以下のプログラムは、変数 が5未満の間、その値をコンソールに出力し続ける例です。i
using System;
class Program
{
static void Main()
{
int i = 0;
// iが5より小さい間、ループを継続する
while (i < 5)
{
Console.WriteLine($"現在の値は {i} です。");
// カウンタをインクリメントしないと無限ループになるので注意
i++;
}
Console.WriteLine("ループが終了しました。");
}
}
現在の値は 0 です。
現在の値は 1 です。
現在の値は 2 です。
現在の値は 3 です。
現在の値は 4 です。
ループが終了しました。
この例では、 という記述が非常に重要です。i++
もしこの記述を忘れてしまうと、 の値は永久に i のままとなり、条件式 0 は常に i < 5 を返し続けます。true
これが「無限ループ」と呼ばれる状態であり、プログラムがフリーズする原因となります。
do-while文との違い:実行タイミングの重要性
文とセットで語られることが多いのが while 文です。do-while
どちらも条件によって繰り返しを行いますが、「最初の1回を実行するかどうか」という点で決定的な違いがあります。
do-while文の構文
do
{
// 最低でも1回は実行される処理
} while (条件式);
文は「後判定ループ」と呼ばれ、ループ内の処理を実行した後に条件式を評価します。do-while
そのため、たとえ最初から条件が であっても、必ず1回は処理が実行されるのが特徴です。false
動作の比較
以下のコードで、条件が最初から満たされていない場合の挙動の違いを確認してください。
using System;
class Program
{
static void Main()
{
int value = 10;
Console.WriteLine("--- while文の開始 ---");
while (value < 5)
{
// 条件 (10 < 5) は最初からfalseなので実行されない
Console.WriteLine("whileの中を通りました。");
}
Console.WriteLine("--- do-while文の開始 ---");
do
{
// 条件判定の前に1回実行される
Console.WriteLine("do-whileの中を通りました。");
} while (value < 5);
}
}
--- while文の開始 ---
--- do-while文の開始 ---
do-whileの中を通りました。
このように、ユーザーに最低1回はメニューを表示したい場合や、リトライ処理などで「まず試行してから結果を確認したい」という場合には が適しています。do-while
一方で、データの個数が0個のときには何もしたくないといった一般的なケースでは を使用するのが定石です。while
ループ制御:breakとcontinueの活用
ループの途中で処理を中断したり、次の繰り返しへスキップしたりしたい場合には、 文と break 文を使用します。continue
break文によるループの脱出
は、その行が実行された瞬間にループを強制終了させ、ブロックの外へ制御を移します。break
特定の条件に合致したときに探索を止めたい場合などに多用されます。
using System;
class Program
{
static void Main()
{
int count = 0;
while (true) // 意図的な無限ループ
{
if (count >= 3)
{
Console.WriteLine("countが3になったのでループを抜けます。");
break; // ループを終了
}
Console.WriteLine($"count = {count}");
count++;
}
}
}
continue文による処理のスキップ
は、現在の回の残り処理をスキップし、即座に次の条件判定(whileの先頭)へ戻るための命令です。continue
特定の条件のときだけ処理を除外したい場合に便利です。
using System;
class Program
{
static void Main()
{
int i = 0;
while (i < 5)
{
i++;
if (i % 2 == 0)
{
// 偶数の場合はこれ以降の処理を飛ばして次の判定へ
continue;
}
Console.WriteLine($"奇数を発見: {i}");
}
}
}
奇数を発見: 1
奇数を発見: 3
奇数を発見: 5
を使用する際の注意点として、カウンタ変数(上記の例では continue)の更新場所があります。i++
もし の後に更新処理を書いてしまうと、その処理が飛ばされて無限ループに陥るリスクがあるため、ループの先頭付近で更新を行うなどの工夫が必要です。continue
while文とfor文の使い分け
C#には、もう一つの強力なループ文として 文が存在します。for
これらはどのように使い分けるべきでしょうか。
| 特徴 | while文 | for文 |
|---|---|---|
| 主な用途 | 繰り返す回数が不明な場合 | 繰り返す回数が決まっている場合 |
| 終了条件 | 真偽値(bool)の状態に依存 | カウンタ変数による範囲指定 |
| 可読性 | シンプルな条件監視に向く | 配列やリストの全要素参照に向く |
一般的に、「10回繰り返す」「このリストの要素数分だけ処理する」というケースでは 文や for 文が適しています。foreach
なぜなら、初期化・条件・更新が一箇所にまとまっており、バグが入り込みにくいからです。
一方で、「ネットワークの受信を待つ」「ファイルが読み終わるまで繰り返す」「有効なユーザー入力が得られるまで聞き直す」といった、いつ終わるか事前には分からないケースでは 文が最もその真価を発揮します。while
実践的な応用例:ユーザー入力のバリデーション
実際のアプリケーション開発でよく見られる 文の利用シーンとして、ユーザーからの入力チェック(バリデーション)があります。while
正しい値が入力されるまで、何度でも入力を促す処理です。
using System;
class Program
{
static void Main()
{
bool isValidInput = false;
int age = 0;
while (!isValidInput)
{
Console.Write("年齢を入力してください(0以上の数値): ");
string input = Console.ReadLine();
// 数値に変換できるか、かつ0以上であるかをチェック
if (int.TryParse(input, out age) && age >= 0)
{
isValidInput = true; // 条件を満たしたのでループ終了へ
}
else
{
Console.WriteLine("エラー: 正しい数値を入力してください。");
}
}
Console.WriteLine($"登録された年齢は {age} 歳です。");
}
}
このように、 型のフラグ変数(上記の例では bool)を用意してループを制御する手法は、複雑な業務ロジックにおいても頻繁に使用されるパターンです。isValidInput
無限ループの活用と回避策
「無限ループ」はプログラムをフリーズさせる危険なものとして扱われることが多いですが、意図的に利用される場面もあります。
例えば、サーバープログラム、ゲームのメインループ、OSのタスクスケジューラなどは、常に動き続ける必要があるため で記述されます。while (true)
安全な無限ループの書き方
無限ループを作成する場合でも、必ず内部で「終了条件(Exit Condition)」を設け、 で抜け出せるように設計するのがプロの書き方です。break
while (true)
{
// 何らかの主要な処理
ProcessTask();
// 終了命令を受け取ったらループを抜ける
if (CheckExitSignal())
{
break;
}
// CPU負荷を抑えるための待機(重要)
System.Threading.Thread.Sleep(10);
}
特にデスクトップアプリやサービス開発において、何も待機処理を入れずに無限ループを回すと、CPU使用率が100%に張り付いてしまう可能性があります。
や、非同期処理であれば Thread.Sleep を適切に組み合わせて、リソースを効率的に使用するように心がけましょう。Task.Delay
while文におけるよくあるミスと注意点
1. 条件式の評価ミス
ループが一度も実行されない、あるいは逆に終わらない原因の多くは、条件式の論理ミスです。
例えば、 と書くべきところを i < 10 と書いてしまうようなミスです。i > 10
境界値(この場合は10を含むか含まないか)についても、テスト時に注意深く確認する必要があります。
2. 変数の更新忘れ
先述の通り、ループ内で条件に関わる変数を更新し忘れると無限ループが発生します。
特に複雑な if 文による分岐がある場合、特定のパスを通った時だけ更新が漏れてしまうといったバグが発生しやすいです。
3. 浮動小数点数(double/float)の比較
文の条件式で while 型などの浮動小数点数を使用するのは避けるべきです。double
計算誤差により、期待した値と完全に一致せず、ループが終了しない可能性があるためです。
繰り返し回数の制御には、必ず整数型( や int)を使用しましょう。long
パフォーマンスとメモリに関する考察
C#の 文自体は非常に低レベルな命令にコンパイルされるため、実行速度におけるオーバーヘッドはほとんどありません。while
しかし、ループ内で行う処理の内容によってはパフォーマンスに大きな影響を与えます。
ループ内でのアロケーション
ループの中で頻繁に を行い、インスタンスを生成すると、ガベージコレクション(GC)の負荷が高まります。new
可能な限り、ループの外でオブジェクトを再利用するか、構造体()や struct を活用してメモリ効率を高めることが、現代的なC#開発では求められます。Span<T>
非同期ループの活用
I/O処理(ファイル読み書きや通信)を含むループの場合、 文の中で同期的な待機を行うと、スレッドをブロックしてしまいます。while
これを防ぐために、モダンなC#では を組み合わせた非同期ループが推奨されます。await
// ネットワークストリームからデータを読み取リ続ける例
while (true)
{
var data = await reader.ReadLineAsync();
if (data == null) break;
ProcessData(data);
}
このように記述することで、データの到着を待っている間、スレッドを他の処理に解放することができ、アプリケーション全体のレスポンスを向上させることができます。
まとめ
C#の 文は、プログラムに柔軟な繰り返し処理をもたらす基礎的なツールです。while
- while文:実行前に条件を判定する「前判定ループ」。回数が決まっていない繰り返しに最適。
- do-while文:実行後に条件を判定する「後判定ループ」。最低1回は必ず実行したい場合に利用。
- 制御命令:
で脱出、breakで次の回へスキップ。continue - 注意点:無限ループの防止、変数の更新、およびCPU負荷への配慮が必要。
プログラミング初心者の方は、まず 文を使って「何かが起こるまで待機する」ようなシンプルなロジックを書いてみることから始めましょう。while
基本をマスターすれば、より複雑な非同期処理や大規模なシステム構築においても、確実な制御フローを設計できるようになります。
ループ処理を正しく理解し、効率的でバグのないコードを目指しましょう。
