C#を用いたプログラミングにおいて、繰り返し処理(ループ)は避けて通れない重要な要素です。
特定の条件に合致した際、その回限りの処理をスキップして次の反復へと移りたい場面が多々あります。
そのような状況で威力を発揮するのが continue文 です。
continue文を適切に使いこなすことで、入れ子(ネスト)の深い複雑な条件分岐を回避し、ソースコードの可読性とメンテナンス性を大幅に向上させることが可能になります。
本記事では、continue文の基本的な使い方から、for、while、foreachといった各ループでの挙動、そして混同されやすいbreak文との決定的な違いについて、具体的なコード例を交えて詳しく解説します。
C#におけるcontinue文とは
C#のcontinue文は、ループの現在の反復処理をその時点で終了させ、次の反復へと制御を移すためのジャンプ文です。
ループ全体を終了させるのではなく、あくまで「現在の回の、continue以降に記述された処理」をスキップする点が特徴です。
通常、ループ処理はブロック内のコードを最後まで実行して次の反復に進みますが、特定の条件下で残りの処理を実行する必要がない場合にcontinue文を使用します。
これにより、不要なelse句を減らし、コードを直線的に記述できる(ガード節のような役割)というメリットがあります。
continue文が使用できるループ
C#においてcontinue文を使用できる反復ステートメントは以下の通りです。
- for文
- foreach文
- while文
- do-while文
これら以外の場所、例えばループ外やswitch文のcase内で単独で使用することはできません(switch文がループ内にある場合は、そのループに対して作用します)。
for文におけるcontinue文の使い方
for文は、繰り返しの回数が決まっている場合に多用されるループ構造です。
for文の中でcontinue文が実行されると、ループ本体の残りの処理はスキップされ、反復子(i++ など)の更新式が実行された後、次の条件評価へと進みます。
以下のプログラムは、0から9までの数値のうち、偶数の場合だけ処理をスキップし、奇数のみを表示する例です。
using System;
class Program
{
static void Main()
{
Console.WriteLine("--- 奇数のみを表示するループ開始 ---");
for (int i = 0; i < 10; i++)
{
// iが偶数の場合は、以降の処理をスキップして次のループ(i++)へ
if (i % 2 == 0)
{
continue;
}
// 偶数の時はここが実行されない
Console.WriteLine($"現在の値: {i}");
}
Console.WriteLine("--- ループ終了 ---");
}
}
--- 奇数のみを表示するループ開始 ---
現在の値: 1
現在の値: 3
現在の値: 5
現在の値: 7
現在の値: 9
--- ループ終了 ---
この例では、i % 2 == 0 が真になる時(0, 2, 4, 6, 8)に continue文が実行されます。
その結果、Console.WriteLine は呼び出されず、すぐに i++ のステップに移行します。
このように、特定の条件を除外したい場合に非常に有効です。
foreach文におけるcontinue文の使い方
foreach文は、配列やリストなどのコレクションの各要素に対して処理を行う際に使用されます。
foreach文の中でcontinue文が実行されると、現在の要素に対する処理を中断し、コレクション内の次の要素を取り出すステップへ移行します。
実務では、リスト内のデータに null や不適切な値が含まれている場合に、それらを無視して処理を続行させる目的でよく使われます。
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var fruits = new List<string> { "Apple", "Banana", "", "Orange", null, "Grape" };
Console.WriteLine("--- 有効なフルーツ名のみを表示 ---");
foreach (var fruit in fruits)
{
// 文字列がnullまたは空文字の場合はスキップ
if (string.IsNullOrEmpty(fruit))
{
continue;
}
// 無効なデータの時は出力されない
Console.WriteLine($"Name: {fruit}");
}
}
}
--- 有効なフルーツ名のみを表示 ---
Name: Apple
Name: Banana
Name: Orange
Name: Grape
データのバリデーション(妥当性確認)において、不適合なデータを早期に除外することで、メインのロジック部分をインデントせずに記述できるため、可読性が高まります。
while文およびdo-while文での注意点
while文やdo-while文でもcontinue文は使用可能ですが、無限ループに陥るリスクがあるため、実装には注意が必要です。
for文とは異なり、while文には「自動的に実行される更新式」がありません。
もしループの末尾で変数を更新している場合、その手前でcontinue文を呼んでしまうと、変数が更新されないまま再び条件判定に戻り、永遠に同じ条件でループし続けることになります。
無限ループを回避する実装例
以下のコードは、不適切な実装と適切な実装の違いを示しています。
using System;
class Program
{
static void Main()
{
int i = 0;
Console.WriteLine("--- while文でのcontinue実行 ---");
while (i < 5)
{
// ここでインクリメントを行わないと、iが3のまま固定され無限ループになる
if (i == 3)
{
i++; // continueの前に必ず更新を行う
continue;
}
Console.WriteLine($"Value: {i}");
i++;
}
}
}
--- while文でのcontinue実行 ---
Value: 0
Value: 1
Value: 2
Value: 4
while文でcontinueを使用する場合は、「ループ脱出条件に関わる変数の更新が確実に行われているか」を必ず確認してください。
continue文とbreak文の違い
ループの制御フローを変更する命令として、continue文と並んで頻繁に使用されるのが break 文です。
これらは混同されやすいですが、挙動は根本的に異なります。
| 項目 | continue文 | break文 |
|---|---|---|
| 主な役割 | 現在の反復をスキップして次の回へ進む | ループ自体を完全に終了させる |
| 実行後の動き | ループの条件判定(または更新式)へ戻る | ループの閉じ括弧 } の直後へ移動する |
| 用途 | 特定の条件下での処理除外 | 特定の条件を満たした時点での探索終了 |
比較コード例
以下のプログラムで、同じ条件式に対する挙動の違いを確認しましょう。
using System;
class Program
{
static void Main()
{
Console.WriteLine("--- continueの場合 ---");
for (int i = 1; i <= 5; i++)
{
if (i == 3) continue;
Console.Write(i + " ");
}
Console.WriteLine("\n--- breakの場合 ---");
for (int i = 1; i <= 5; i++)
{
if (i == 3) break;
Console.Write(i + " ");
}
}
}
--- continueの場合 ---
1 2 4 5
--- breakの場合 ---
1 2
continue文は「3」だけを飛ばして「4, 5」と続けますが、break文は「3」に到達した瞬間にループそのものを放棄します。
この違いを理解しておくことは、バグのないプログラムを書くための基本です。
ネスト(入れ子)構造におけるcontinue文の挙動
ループの中にさらにループがある「二重ループ」などの環境において、continue文がどのループに影響を与えるのかを理解することは重要です。
C#のcontinue文は、「それが記述されている最も内側のループ」に対してのみ作用します。
外側のループをスキップさせたい場合は、フラグ変数を使用するか、メソッドを分割して return するなどの工夫が必要です。
using System;
class Program
{
static void Main()
{
for (int i = 1; i <= 3; i++)
{
for (int j = 1; j <= 3; j++)
{
if (j == 2)
{
// 内側のループ(jのループ)の2回目のみスキップ
continue;
}
Console.WriteLine($"i={i}, j={j}");
}
}
}
}
i=1, j=1
i=1, j=3
i=2, j=1
i=2, j=3
i=3, j=1
i=3, j=3
この結果からわかる通り、j == 2 の時にcontinueが呼ばれても、外側の i のループが中断されることはありません。
内側のループの「次の j」へと処理が移るだけです。
実践的な活用シーン:ガード節としての利用
continue文の最も効果的な使い方のひとつが、「ガード節」としての利用です。
ガード節とは、処理の対象外となる条件をメソッドやループの冒頭で先にチェックし、除外してしまう手法のことです。
これを使わない場合、以下のように if 文のネストが深くなりがちです。
悪い例(ネストが深い)
foreach (var user in users)
{
if (user != null)
{
if (user.IsActive)
{
if (user.HasPermission)
{
// ここにメインの処理
DoProcess(user);
}
}
}
}
良い例(continueでフラットにする)
foreach (var user in users)
{
if (user == null) continue;
if (!user.IsActive) continue;
if (!user.HasPermission) continue;
// ここにメインの処理
DoProcess(user);
}
後者の書き方の方が、「どのような条件の時に処理が行われるのか」が明確であり、ロジックの見通しが非常に良くなります。
C#のコーディング規約やクリーンコードの観点からも、このようにcontinueを活用してネストを浅く保つことが推奨されます。
パフォーマンスと注意点
continue文の使用自体がプログラムの実行速度を著しく低下させることはありません。
コンパイラによって効率的なジャンプ命令に最適化されるため、パフォーマンス上の懸念はほぼ不要です。
しかし、乱用には注意が必要です。
一つのループ内に多数のcontinue文が散在していると、ループの制御フローが複雑になり、どの条件で何が実行されるのかを追跡するのが困難になります。
可読性を保つためのポイント
- continue文はなるべくループの先頭付近に集める。
- 条件が複雑すぎる場合は、判定ロジックを別のメソッドに切り出す。
- 「スキップ」ではなく「実行」の条件が単純であれば、通常の
if (条件) { 処理 }を使う方が自然な場合もある。
まとめ
C#の continue文 は、ループ処理において特定の反復をスキップし、効率的かつクリーンなコードを書くための強力なツールです。
- for文では、現在の処理を飛ばして更新式(i++など)へ進む。
- foreach文では、次の要素の取り出しへ進む。
- while文では、無限ループを防ぐために更新式の位置に注意する。
- break文との違いは、ループを「継続する」か「完全に終了する」かにある。
- ガード節として利用することで、コードのネストを浅くし、可読性を向上させることができる。
プログラミング初心者の方は、まずは「除外したい条件があればcontinueを使う」という単純なルールから始めてみてください。
コードの見た目がスッキリし、バグの少ない、メンテナンスしやすいプログラムが書けるようになるはずです。
複雑なループ制御が必要になった際、この記事で紹介した挙動の違いを思い出し、最適な制御フローを選択してください。






