C#のfor
文は、決まった回数だけ処理を繰り返したいときに最も素直に使える構文です。
本記事では、基本構造と実行の流れを丁寧に解説し、0からn未満・1からnまで・逆順・ステップ変更・配列や文字列の走査などの代表的パターンを具体例と出力付きで示します。
初心者の方がつまずきやすい注意点も併せて理解しましょう。
C#のfor文とは?回数指定の基本
for文の役割と使いどころ
for文は、繰り返し回数やインデックスを自分で管理したい場合に使います。
配列や文字列の各要素へ位置指定してアクセスするとき、ある回数だけ同じ処理を行いたいとき、一定ステップで値を変化させたいときなどに適しています。
開始値・終了条件・更新方法を1か所にまとめて記述できるため、処理の見通しが良く、意図が読み取りやすいのが特長です。
C#のfor文の書き方 基本構造
基本構文(初期化 条件 更新)
典型的な書式と各部の意味
以下が基本の書式です。
初期化・条件・更新の3つをヘッダー内にまとめます。
// for (初期化; 条件; 更新)
for (int i = 0; i < 5; i++)
{
// 本体: ここに繰り返したい処理を書く
Console.WriteLine(i);
}
- 初期化: ループ前に一度だけ実行され、
i
の開始値などを決めます。 - 条件: 各反復の開始時に評価され、
true
なら本体を実行、false
ならループ終了です。 - 更新: 各反復の末尾で実行され、インデックスを次の状態に進めます。
3つを1行で把握できるため、回数指定の繰り返しでは最初に検討すべき選択肢です。
初期化の書き方(ループ変数)
代表例と複数初期化
初期化では通常、ループ変数の宣言と初期値の設定を行います。
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i);
}
複数の変数を同時に初期化することもできます。
for (int i = 0, j = 10; i < j; i++, j--)
{
// iは増加、jは減少。両者が交わるまで続く
Console.WriteLine($"i={i}, j={j}");
}
ループ変数はできるだけfor文の初期化部で宣言し、スコープを最小化するとコードの安全性が高まります。
条件の書き方(終了条件)
論理式で継続を制御
条件にはbool
に評価される式を書きます。
例えばi < n
やi <= n
などです。
どこでループを終えるか(終了条件)を明確にすると、オフバイワンエラーを防げます。
int n = 5;
for (int i = 0; i < n; i++)
{
Console.Write($"{i} ");
}
// 0 1 2 3 4
更新の書き方(i++など)
ステップの増減と複合代入
更新では、多くの場合i++
(1ずつ増加)、あるいはi--
(1ずつ減少)を使います。
2以上で刻む場合はi += 2
のように複合代入を用います。
for (int i = 0; i < 10; i += 2) // 2ずつ増やす
{
Console.Write($"{i} ");
}
// 0 2 4 6 8
更新はループ本体の最後に実行される点に注意してください。
ループ変数のスコープ
for内宣言の有効範囲
forの初期化で宣言した変数は、そのfor文の中でのみ有効です。
外側からは参照できません。
スコープを限定することで変数の取り違えを防げます。
// コンパイルエラーになる例(コメントで説明)
// Console.WriteLine(i); // ここにはiは存在しない
for (int i = 0; i < 2; i++)
{
Console.WriteLine(i); // OK: for文の内部
}
// Console.WriteLine(i); // ここでもiは見えない
スコープを広くしたい場合は、forの外で変数を宣言し、初期化部では代入だけを行う方法もあります。
ただし必要がない限りはスコープを狭く保つことをおすすめします。
C#のfor文の実行の流れと基本パターン
実行順序(初期化→条件→本体→更新)
実際のログで順序を可視化
以下のプログラムで、実行順序をはっきり確認できます。
using System;
class Program
{
static void Main()
{
int i; // 外で宣言して順序を見やすくする
Console.WriteLine("開始");
for (i = 0; i < 2; i++)
{
Console.WriteLine($"本体: i={i}");
}
Console.WriteLine("終了");
}
}
開始
本体: i=0
本体: i=1
終了
実際には、内部で初期化 → 条件判定 → 本体 → 更新 → 条件判定 → 本体 → 更新 …
と進み、条件がfalse
になった時点で抜けます。
0からn未満まで回す
最もよく使うパターン
配列や文字列のインデックスに一致する、基本中の基本です。
using System;
class Program
{
static void Main()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Console.Write($"{i} ");
}
}
}
0 1 2 3 4
1からnまで回す
人間の数え方に合わせたい場合
開始値を1に、条件をi <= n
にします。
using System;
class Program
{
static void Main()
{
int n = 5;
for (int i = 1; i <= n; i++)
{
Console.Write($"{i} ");
}
}
}
1 2 3 4 5
逆順に回す
大きい方から小さい方へ
降順では、開始を最大値にしてi--
で減らします。
using System;
class Program
{
static void Main()
{
int n = 5;
for (int i = n - 1; i >= 0; i--)
{
Console.Write($"{i} ");
}
}
}
4 3 2 1 0
2ずつなどステップを変える
偶数だけ・奇数だけを走査
ステップを調整すると、偶数インデックスのみ処理するなどの最適化ができます。
using System;
class Program
{
static void Main()
{
for (int i = 0; i < 10; i += 2) // 偶数のみ
{
Console.Write($"{i} ");
}
}
}
0 2 4 6 8
配列や文字列の長さを使って回す
Lengthを使うのが安全で読みやすい
配列や文字列はLength
プロパティを持ちます。
境界を<
で比較し、0
からLength - 1
までアクセスするのが基本です。
using System;
class Program
{
static void Main()
{
int[] numbers = { 10, 20, 30 };
for (int i = 0; i < numbers.Length; i++)
{
Console.Write($"{numbers[i]} ");
}
Console.WriteLine();
string text = "CSharp";
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
Console.Write($"{c} ");
}
}
}
10 20 30
C S h a r p
配列・文字列ともに0始まりのインデックスである点を覚えておくと、境界エラーを避けやすくなります。
C#のfor文の注意点 初心者向け
<と<=の違い
典型条件の違いと回数への影響
< と <= の違いは実行回数に直結します。
想定と1回ずれる「オフバイワン」に注意しましょう。
開始 | 条件 | 実行されるiの値 | 回数 |
---|---|---|---|
0 | i < n | 0,1,2,…,n-1 | n回 |
1 | i <= n | 1,2,3,…,n | n回 |
0 | i <= n | 0,1,2,…,n | n+1回 |
意図せずn+1回になるケースは特に注意が必要です。
更新忘れで終わらない
無限ループの典型
更新を書き忘れるとループが終わらなくなることがあります。
using System;
class Program
{
static void Main()
{
// 注意: 更新がないためiが増えず、条件がずっとtrueになる
for (int i = 0; i < 3; /* i++ を忘れている */)
{
Console.WriteLine("終わらない例(実行しないでください)");
break; // 実害防止のため即座に抜ける(説明用)
}
}
}
実際の開発では、初期化・条件・更新の3点セットを必ず確認しましょう。
インデックス範囲外に注意
IndexOutOfRangeExceptionの回避
配列や文字列は0
からLength - 1
までが有効です。
Lengthと同じインデックスへアクセスすると例外になります。
using System;
class Program
{
static void Main()
{
int[] a = { 1, 2, 3 };
// Console.WriteLine(a[3]); // IndexOutOfRangeException (コメントアウトしています)
for (int i = 0; i < a.Length; i++)
{
Console.Write($"{a[i]} ");
}
}
}
1 2 3
条件を常にi < 配列.Length
とする習慣が安全です。
回数が大きいと時間がかかる
規模意識と軽微な最適化のヒント
繰り返し回数が大きくなると比例して処理時間が伸びます。
まずはアルゴリズムの改善(計算量の削減)を検討し、それでも厳しい場合に以下のような軽微な工夫を行います。
- 不変な値はループ外で一度だけ取得する(特に計算コストが高い場合)。
例: コレクションのCount
を毎回計算するようなケースではループ前に一度変数へ退避。 - ループ内での文字列連結はビルダー系(
StringBuilder
)の利用を検討。
なお、配列や文字列のLength
は定数時間で取得できるため、通常はそのまま使っても問題ありません。
まとめ
for文は「初期化・条件・更新」を1か所に集約できるため、回数を指定した繰り返しに最適です。
0からn未満・1からnまで・逆順・ステップ変更・配列や文字列の走査など、よくあるパターンを正しく使い分ければ、多くの反復処理を簡潔に、安全に記述できます。
最後に、< と <= の違い、更新忘れ、インデックスの境界は初心者がつまずきやすい要点です。
記事のサンプルと出力を手元で再現しながら、「何回回るか」「どこで終わるか」を常に明確にする習慣を身につけてください。