C#のインクリメント演算子を基礎から解説|++iとi++の違い・使い方・注意点までわかる
はじめに
C#で繰り返し処理やカウンター処理を書くときによく使うのが、インクリメント演算子です。
インクリメント演算子は、変数の値を「1増やす」ための演算子で、C#では ++ を使って表します。
C#int i = 0;
i++;
Console.WriteLine(i); // 1
一見するととても単純ですが、C#のインクリメントには i++ と ++i という2つの書き方があります。単独で使う場合はどちらも同じように見えますが、式の中で使うと結果が変わることがあります。
この記事では、C#のインクリメント演算子について、基本的な意味から ++i と i++ の違い、for文での使い方、注意点、スレッド処理での扱いまで初心者にもわかりやすく解説します。
1. C#のインクリメント演算子とは
1-1. インクリメントの意味と「1増やす」処理の基本
インクリメントとは、数値を1増やす処理のことです。
たとえば、変数 i の値が 5 のとき、インクリメントすると 6 になります。
C#int i = 5;
i++;
Console.WriteLine(i); // 6
プログラムでは、回数を数えたり、配列の位置を1つ進めたり、ループのたびにカウンターを増やしたりする場面でよく使います。
C#では、次のような処理をインクリメント演算子で短く書けます。
C#i = i + 1;
これを ++ を使って書くと、次のようになります。
C#i++;
つまり、i++ は「変数 i の値を1増やす」という意味です。
1-2. C#で使うインクリメント演算子「++」の書き方
C#のインクリメント演算子は ++ です。
書き方には、次の2種類があります。
C#i++;
++i;
i++ は後置インクリメント、++i は前置インクリメントと呼ばれます。
どちらも変数 i の値を1増やしますが、式の中で使ったときに「増やすタイミング」と「式の値」が異なります。
単独で使う場合は、次のようにどちらも結果は同じです。
C#int a = 10;
a++;
int b = 10;
++b;
Console.WriteLine(a); // 11
Console.WriteLine(b); // 11
1-3. インクリメントとデクリメント「--」の違い
インクリメントが「1増やす」処理であるのに対して、デクリメントは「1減らす」処理です。
C#では、デクリメント演算子として -- を使います。
C#int count = 5;
count--;
Console.WriteLine(count); // 4
インクリメントとデクリメントの違いは次のとおりです。
C#int x = 10;
x++; // xを1増やす
x--; // xを1減らす
ループ処理でカウントアップしたいときは ++、カウントダウンしたいときは -- を使います。
C#for (int i = 5; i > 0; i--)
{
Console.WriteLine(i);
}
このコードでは、i が 5 から始まり、ループのたびに 1 ずつ減っていきます。
1-4. 代入式「i = i + 1」「i += 1」との違い
C#で変数を1増やす方法は、インクリメント演算子だけではありません。
主に次の3つの書き方があります。
C#i = i + 1;
i += 1;
i++;
どれも基本的には i を1増やす処理です。
C#int i = 0;
i = i + 1; // 1
i += 1; // 2
i++; // 3
Console.WriteLine(i); // 3
i = i + 1 は最も明示的な書き方です。初心者にも意味がわかりやすい反面、少し長くなります。
i += 1 は複合代入演算子を使った書き方です。i に 1 を加えて、その結果を再び i に代入します。
i++ はインクリメント専用の短い書き方です。ループのカウンターなど、1ずつ増やす処理でよく使われます。
2. C#のインクリメント演算子の基本的な使い方
2-1. 変数に対してインクリメントする基本コード
インクリメント演算子は、変数に対して使います。
C#int count = 0;
count++;
Console.WriteLine(count); // 1
このコードでは、最初に count に 0 を代入しています。その後、count++ によって値が1増え、1 になります。
複数回インクリメントすることもできます。
C#int count = 0;
count++;
count++;
count++;
Console.WriteLine(count); // 3
count++ を3回実行しているため、最終的な値は 3 になります。
2-2. int型・long型など数値型での使用例
インクリメント演算子は、int 型だけでなく、さまざまな数値型で使えます。
C#int a = 1;
a++;
long b = 100L;
b++;
double c = 1.5;
c++;
decimal d = 10.5m;
d++;
Console.WriteLine(a); // 2
Console.WriteLine(b); // 101
Console.WriteLine(c); // 2.5
Console.WriteLine(d); // 11.5
double や decimal のような小数型でも、++ を使うと値が 1 増えます。
ただし、実際のコードでは小数値を1ずつ増やすよりも、整数型のカウンターに使う場面の方が多いです。
2-3. for文でカウンターを増やす使い方
C#のインクリメント演算子が最もよく使われる場面の1つが for 文です。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
実行結果は次のようになります。
0
1
2
3
4
for 文の最後にある i++ は、ループが1回終わるたびに i を1増やします。
for 文は次の3つの部分で構成されています。
C#for (初期化; 条件式; 更新処理)
{
// 繰り返す処理
}
先ほどのコードでは、次の意味になります。
C#for (int i = 0; i < 5; i++)
int i = 0 は、カウンター変数 i を0から始める処理です。
i < 5 は、i が5未満の間だけ繰り返す条件です。
i++ は、ループのたびに i を1増やす更新処理です。
2-4. while文・do while文で使う場合の注意点
while 文でもインクリメント演算子はよく使います。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
i++;
}
実行結果は for 文の例と同じです。
0
1
2
3
4
while 文で注意したいのは、インクリメントを忘れると無限ループになる可能性があることです。
C#int i = 0;
while (i < 5)
{
Console.WriteLine(i);
// i++ を忘れている
}
このコードでは、i の値がずっと 0 のままなので、i < 5 が常に true になり、ループが終わりません。
do while 文でも同じように注意が必要です。
C#int i = 0;
do
{
Console.WriteLine(i);
i++;
}
while (i < 5);
while 文や do while 文では、カウンターをどこで増やすかを意識することが大切です。
2-5. 配列やListのインデックス操作で使う例
インクリメント演算子は、配列や List の要素を順番に処理するときにも使います。
C#string[] names = { "Alice", "Bob", "Charlie" };
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}
このコードでは、i を配列のインデックスとして使っています。
最初は i = 0 なので names[0]、次に names[1]、最後に names[2] が表示されます。
List<T> でも同じように使えます。
C#List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
for (int i = 0; i < names.Count; i++)
{
Console.WriteLine(names[i]);
}
配列では Length、List では Count を使う点に注意しましょう。
3. ++iとi++の違い
3-1. 前置インクリメント「++i」とは
++i は、前置インクリメントと呼ばれます。
前置インクリメントは、変数の値を先に1増やしてから、その値を式の結果として使います。
C#int i = 1;
int result = ++i;
Console.WriteLine(i); // 2
Console.WriteLine(result); // 2
この例では、++i によって i が先に 2 になります。その後、増えた後の値である 2 が result に代入されます。
つまり、++i は「先に増やしてから使う」と考えるとわかりやすいです。
3-2. 後置インクリメント「i++」とは
i++ は、後置インクリメントと呼ばれます。
後置インクリメントは、現在の値を式の結果として使った後に、変数の値を1増やします。
C#int i = 1;
int result = i++;
Console.WriteLine(i); // 2
Console.WriteLine(result); // 1
この例では、result には増える前の値である 1 が代入されます。その後、i の値が 2 になります。
つまり、i++ は「使ってから増やす」と考えると理解しやすいです。
3-3. 単独で使う場合は結果が同じになる理由
++i と i++ は、単独の文として使う場合は結果が同じです。
C#int a = 1;
++a;
int b = 1;
b++;
Console.WriteLine(a); // 2
Console.WriteLine(b); // 2
どちらも最終的には変数の値を1増やしているため、単独で使う限り結果は変わりません。
違いが出るのは、インクリメント演算子を代入式やメソッド呼び出しなど、別の式の中で使った場合です。
3-4. 式の中で使うと結果が変わる理由
++i と i++ は、式の中で使うと評価される値が異なります。
C#int i = 10;
int a = i++;
int b = ++i;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(i);
このコードの流れを順番に見てみましょう。
最初に i は 10 です。
C#int a = i++;
ここでは、a に増える前の 10 が代入され、その後 i は 11 になります。
次に、次の処理が実行されます。
C#int b = ++i;
ここでは、先に i が 12 になり、その値が b に代入されます。
そのため、実行結果は次のようになります。
10
12
12
このように、前置と後置では「式の値」として使われるタイミングが違います。
3-5. Console.WriteLineで確認する++iとi++の違い
違いを確認するには、Console.WriteLine で表示してみるのがわかりやすいです。
C#int i = 1;
Console.WriteLine(i++); // 1
Console.WriteLine(i); // 2
i++ は、表示に使われる値は増える前の 1 です。その後で i が 2 になります。
一方、++i の場合は次のようになります。
C#int i = 1;
Console.WriteLine(++i); // 2
Console.WriteLine(i); // 2
++i は先に i を増やすため、表示される値は 2 になります。
この違いは、初心者がつまずきやすいポイントです。
3-6. どちらを使うべきか判断するポイント
基本的には、単独で使う場合は i++ を使うことが多いです。
C#i++;
特に for 文では、慣習的に i++ がよく使われます。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
一方で、式の中で値をすぐに増やしてから使いたい場合は ++i を使います。
C#int i = 0;
int value = ++i; // valueは1
ただし、初心者のうちは式の中で ++i や i++ を使いすぎない方が安全です。読みやすさを重視するなら、次のように処理を分けて書くとわかりやすくなります。
C#i++;
int value = i;
4. インクリメント演算子の実践的な使用例
4-1. ループ処理でカウントアップする
インクリメント演算子は、ループの回数を数えるときに便利です。
C#for (int i = 1; i <= 5; i++)
{
Console.WriteLine($"{i}回目の処理です");
}
実行結果は次のようになります。
1回目の処理です
2回目の処理です
3回目の処理です
4回目の処理です
5回目の処理です
このように、i++ を使うことで、処理のたびにカウンターを1ずつ増やせます。
4-2. 条件分岐と組み合わせて回数を数える
条件に一致した回数を数える場合にも、インクリメント演算子を使えます。
C#int[] scores = { 80, 45, 90, 60, 30 };
int passCount = 0;
foreach (int score in scores)
{
if (score >= 60)
{
passCount++;
}
}
Console.WriteLine($"合格者数: {passCount}");
このコードでは、点数が60点以上の場合に passCount++ を実行しています。
実行結果は次のようになります。
合格者数: 3
条件に合った件数を数える処理では、count++ のような書き方がよく使われます。
4-3. 配列の要素を順番に処理する
配列の要素を順番に処理する場合も、インクリメント演算子が役立ちます。
C#int[] numbers = { 10, 20, 30, 40 };
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}
i++ によってインデックスが 0、1、2、3 と進むため、配列の要素を先頭から順番に取り出せます。
配列のインデックスは0から始まるため、条件式は i < numbers.Length と書くのが基本です。
C#for (int i = 0; i < numbers.Length; i++)
i <= numbers.Length と書くと、最後に存在しないインデックスへアクセスしてエラーになるので注意しましょう。
4-4. メソッドの戻り値や引数で使う場合の挙動
インクリメント演算子は、メソッドの引数として使うこともできます。
C#static void PrintNumber(int number)
{
Console.WriteLine(number);
}
int i = 1;
PrintNumber(i++);
Console.WriteLine(i);
実行結果は次のようになります。
1
2
PrintNumber(i++) では、メソッドに渡される値は増える前の 1 です。その後、i は 2 になります。
一方、前置インクリメントを使うと結果が変わります。
C#int i = 1;
PrintNumber(++i);
Console.WriteLine(i);
実行結果は次のようになります。
2
2
++i は先に増やしてから引数として渡すため、メソッドには 2 が渡されます。
このような書き方は動作を理解していれば使えますが、読み手が混乱しやすいため、業務コードでは処理を分けて書く方が安全です。
C#i++;
PrintNumber(i);
4-5. カウンター変数を使った簡単なサンプルプログラム
次は、偶数の個数を数える簡単なサンプルです。
C#int[] numbers = { 1, 2, 3, 4, 5, 6 };
int evenCount = 0;
foreach (int number in numbers)
{
if (number % 2 == 0)
{
evenCount++;
}
}
Console.WriteLine($"偶数の数: {evenCount}");
実行結果は次のようになります。
偶数の数: 3
number % 2 == 0 は、数値が偶数かどうかを判定しています。偶数だった場合に evenCount++ を実行し、偶数の数を1つずつ数えています。
このように、インクリメント演算子は「条件に合うものを数える」処理で非常によく使われます。
5. C#でインクリメント演算子を使うときの注意点
5-1. 式の中で多用すると読みづらくなる
インクリメント演算子は便利ですが、式の中で多用するとコードが読みづらくなります。
C#int i = 0;
int result = i++ + ++i;
このようなコードは、結果をすぐに理解しにくく、バグの原因になりやすいです。
読みやすさを重視するなら、次のように分けて書く方が安全です。
C#int i = 0;
int first = i;
i++;
i++;
int second = i;
int result = first + second;
実際の開発では、短く書けることよりも、他の人が読みやすいことの方が重要です。
5-2. 同じ変数を1つの式で何度もインクリメントしない
同じ変数を1つの式の中で何度もインクリメントすると、意図がわかりにくくなります。
C#int i = 1;
int result = i++ + i++ + ++i;
このようなコードは、動作を追うのが難しくなります。
処理自体はC#のルールに従って実行されますが、読み間違いや修正ミスが起きやすくなります。
次のように、インクリメントと計算を分けて書く方がわかりやすいです。
C#int i = 1;
int a = i;
i++;
int b = i;
i++;
i++;
int c = i;
int result = a + b + c;
特にチーム開発では、複雑な式の中に ++ を入れないように意識しましょう。
5-3. オーバーフローが起きるケース
数値型には扱える範囲があります。たとえば int 型の最大値を超えてインクリメントすると、オーバーフローが発生します。
C#int i = int.MaxValue;
i++;
Console.WriteLine(i);
unchecked の文脈では、int.MaxValue の次は int.MinValue に回り込みます。
-2147483648
これは、int 型が表現できる最大値を超えたためです。
通常のカウンターではあまり起きませんが、大量データの処理や長時間動作するプログラムでは注意が必要です。
5-4. checked・uncheckedによるオーバーフロー時の違い
C#では、整数演算のオーバーフローを検出するために checked を使えます。
C#checked
{
int i = int.MaxValue;
i++; // OverflowException
}
checked ブロック内でオーバーフローが発生すると、OverflowException が発生します。
一方、unchecked を使うと、オーバーフローしても例外は発生せず、値が回り込みます。
C#unchecked
{
int i = int.MaxValue;
i++;
Console.WriteLine(i); // -2147483648
}
金額や在庫数など、オーバーフローが致命的な問題になる処理では、checked を使って検出できるようにすると安全です。
5-5. nullable型ではそのまま使えない場合がある
nullable型は、値型に null を代入できるようにした型です。
C#int? count = 1;
count++;
Console.WriteLine(count); // 2
値が入っている場合は、nullable型でもインクリメントできます。
ただし、値が null の場合は注意が必要です。
C#int? count = null;
count++;
Console.WriteLine(count); // null
nullable型に対するインクリメントでは、元の値が null の場合、結果も null になります。
そのため、null の可能性がある値をカウントアップしたい場合は、事前に値を確認するのが安全です。
C#int? count = null;
count = (count ?? 0) + 1;
Console.WriteLine(count); // 1
?? は、左側が null のときに右側の値を使う演算子です。この例では、count が null なら 0 として扱い、そこに 1 を足しています。
5-6. プロパティやインデクサに使うときの注意点
C#では、プロパティに対してもインクリメント演算子を使えます。
C#class Counter
{
public int Count { get; set; }
}
Counter counter = new Counter();
counter.Count++;
Console.WriteLine(counter.Count); // 1
ただし、プロパティに対する ++ は、内部的には値を取得して、1増やして、再び設定する処理になります。
イメージとしては次のような処理です。
C#counter.Count = counter.Count + 1;
インデクサでも同じように使えます。
C#int[] numbers = { 10, 20, 30 };
numbers[0]++;
Console.WriteLine(numbers[0]); // 11
ただし、プロパティやインデクサの getter や setter に重い処理がある場合、++ を使うことで意図せず複数の処理が実行されることがあります。
単純なフィールドやローカル変数に使う場合よりも、動作を意識して使いましょう。
6. インクリメント演算子と似た処理の使い分け
6-1. i++とi += 1の違い
i++ と i += 1 は、どちらも i を1増やす処理です。
C#int i = 0;
i++;
i += 1;
Console.WriteLine(i); // 2
単純に1増やすだけなら、結果は同じです。
ただし、意味合いとしては少し違います。
i++ は「1増やす」ことに特化した書き方です。
i += 1 は「指定した値を加算する」書き方です。
そのため、1ずつ増やすカウンターには i++、増やす値を変更する可能性がある場合は i += n の方が自然です。
C#i += 5; // 5増やす
6-2. i++とi = i + 1の違い
i++ と i = i + 1 も、基本的には同じ結果になります。
C#int i = 10;
i = i + 1;
i++;
Console.WriteLine(i); // 12
i = i + 1 は、右辺の i + 1 を計算して、その結果を左辺の i に代入する書き方です。
初心者にとっては意味がわかりやすいですが、カウンター処理では少し冗長に見えることがあります。
一方、i++ は短く書けるため、ループやカウント処理でよく使われます。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
6-3. 2以上増やしたい場合は+=を使う
インクリメント演算子 ++ は、必ず1だけ増やします。
2以上増やしたい場合は、+= を使います。
C#int i = 0;
i += 2;
Console.WriteLine(i); // 2
たとえば、偶数だけを処理したい場合は次のように書けます。
C#for (int i = 0; i <= 10; i += 2)
{
Console.WriteLine(i);
}
実行結果は次のようになります。
0
2
4
6
8
10
++ は1ずつ増やすとき、+= は任意の数だけ増やすときに使うと考えるとわかりやすいです。
6-4. 可読性を重視するならどの書き方がよいか
可読性を重視するなら、処理の意図に合った書き方を選ぶことが大切です。
1ずつ増やすカウンターなら、i++ が自然です。
C#count++;
特定の値を加算したいなら、+= が自然です。
C#total += price;
初心者向けに処理を明確に見せたい場合や、説明用のコードでは i = i + 1 を使うこともあります。
C#i = i + 1;
実務では、短さよりも「何をしているかすぐにわかること」が重要です。
6-5. 初心者が迷いやすい書き方の選び方
初心者のうちは、次のように使い分けると迷いにくくなります。
1ずつ数えるだけなら、i++ を使います。
C#i++;
1以外の数を足すなら、+= を使います。
C#i += 3;
処理を明確に学びたいときは、i = i + 1 で考えます。
C#i = i + 1;
そして、式の中で i++ や ++i を使うのは、動作をしっかり理解してからにしましょう。
C#int result = i++; // 初心者のうちは注意
可読性を優先するなら、次のように分けて書くのがおすすめです。
C#int result = i;
i++;
7. インクリメント演算子の応用知識
7-1. ユーザー定義型で演算子オーバーロードする方法
C#では、自分で作った型に対して ++ 演算子の動作を定義できます。これを演算子オーバーロードと呼びます。
C#class Counter
{
public int Value { get; }
public Counter(int value)
{
Value = value;
}
public static Counter operator ++(Counter counter)
{
return new Counter(counter.Value + 1);
}
}
このように operator ++ を定義すると、Counter 型の変数に対して ++ を使えるようになります。
C#Counter counter = new Counter(10);
counter++;
Console.WriteLine(counter.Value); // 11
ただし、演算子オーバーロードは便利な反面、使い方によってはコードの意味がわかりにくくなります。
++ を使ったときに自然に「1増える」と理解できる型にだけ使うのがよいでしょう。
7-2. マルチスレッド処理ではi++が安全ではない理由
i++ は一見すると1つの処理に見えますが、実際には次のような流れで実行されます。
C#i = i + 1;
さらに細かく見ると、次のような処理になります。
現在の値を読み取る
1を足す
結果を書き戻す
マルチスレッド環境では、複数のスレッドが同時に同じ変数を更新することがあります。
C#counter++;
この処理を複数スレッドが同時に実行すると、値の読み取りと書き込みが競合し、期待した回数だけ増えない可能性があります。
たとえば、2つのスレッドが同時に counter の値 10 を読み取り、それぞれが 11 を書き戻すと、本来は 12 になるはずが 11 になってしまいます。
そのため、マルチスレッド処理では通常の i++ はスレッドセーフではありません。
7-3. Interlocked.Incrementを使うべきケース
マルチスレッドで安全にカウンターを増やしたい場合は、Interlocked.Increment を使います。
C#using System.Threading;
int counter = 0;
Interlocked.Increment(ref counter);
Interlocked.Increment は、複数スレッドから同時に呼び出されても安全に値を1増やせます。
たとえば、並列処理で完了件数を数えたい場合などに使います。
C#using System.Threading;
using System.Threading.Tasks;
int counter = 0;
Parallel.For(0, 1000, i =>
{
Interlocked.Increment(ref counter);
});
Console.WriteLine(counter); // 1000
通常の counter++ では、スレッドの競合により 1000 にならない可能性があります。複数スレッドから共有変数を更新する場合は、Interlocked.Increment を検討しましょう。
7-4. パフォーマンス面で++iとi++に差はあるのか
C#で単純な数値型に対して ++i と i++ を単独で使う場合、実用上のパフォーマンス差を気にする必要はほとんどありません。
C#i++;
++i;
どちらも最終的には変数を1増やす処理です。
C++など一部の言語では、型や状況によって前置インクリメントの方が効率的と説明されることがありますが、C#の通常の int や long のカウンターでは、可読性や慣習を優先して問題ありません。
C#では、for 文の更新式としては i++ がよく使われます。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
パフォーマンスを理由に無理に ++i を選ぶよりも、チームのコーディング規約や読みやすさに合わせる方が大切です。
7-5. コーディング規約で意識したいポイント
インクリメント演算子を使うときは、次のような点を意識するとコードが読みやすくなります。
単独のカウンター更新では、慣習に合わせて i++ を使うことが多いです。
C#i++;
式の中でインクリメントを使う場合は、読み手が迷わないかを考えます。
C#int value = i++; // 意図が伝わるか注意
複雑になりそうなら、処理を分けます。
C#int value = i;
i++;
また、同じ変数を1つの式で何度もインクリメントする書き方は避けた方が無難です。
C#int result = i++ + ++i; // 読みづらい
コードは書いた本人だけでなく、後から読む人にとってもわかりやすいことが重要です。
8. 初心者がよく間違えるインクリメントの例
8-1. i++したのに表示結果が増えていないように見える例
初心者がよく混乱するのが、次のようなコードです。
C#int i = 1;
Console.WriteLine(i++);
この実行結果は次のようになります。
1
i++ と書いているので 2 が表示されると思うかもしれませんが、後置インクリメントでは、先に現在の値を使い、その後で値を増やします。
そのため、表示されるのは増える前の 1 です。
値が増えているか確認するには、もう一度表示してみましょう。
C#int i = 1;
Console.WriteLine(i++); // 1
Console.WriteLine(i); // 2
このように、i++ した後の変数自体はきちんと増えています。
8-2. for文の条件式を間違えて無限ループになる例
for 文では、条件式や更新式を間違えると無限ループになることがあります。
C#for (int i = 0; i < 5; i--)
{
Console.WriteLine(i);
}
このコードでは、i は 0 から始まります。条件は i < 5 です。
しかし、更新式が i-- になっているため、i は -1、-2、-3 と減っていきます。
すると、i < 5 がずっと true のままになり、ループが終わりません。
正しくは、次のように i++ を使います。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
ループでは、条件式と更新式の方向が合っているかを必ず確認しましょう。
8-3. 前置と後置を混同して計算結果がずれる例
++i と i++ を混同すると、計算結果がずれることがあります。
C#int i = 1;
int result = i++ * 10;
Console.WriteLine(result); // 10
Console.WriteLine(i); // 2
i++ は増える前の値を使うため、result は 1 * 10 で 10 になります。
一方、前置インクリメントを使うと結果が変わります。
C#int i = 1;
int result = ++i * 10;
Console.WriteLine(result); // 20
Console.WriteLine(i); // 2
++i は先に i を 2 にしてから計算するため、result は 2 * 10 で 20 になります。
このような違いがあるため、式の中で使う場合は注意が必要です。
8-4. 変数の初期化忘れによるエラー
C#では、ローカル変数を初期化せずに使うとコンパイルエラーになります。
C#int count;
count++;
Console.WriteLine(count);
このコードは、count に初期値が入っていないためエラーになります。
正しくは、次のように初期値を代入してからインクリメントします。
C#int count = 0;
count++;
Console.WriteLine(count); // 1
カウンター変数を使う場合は、最初に 0 などの初期値を設定することを忘れないようにしましょう。
8-5. 複雑な式にインクリメントを入れてバグになる例
次のように、複雑な式の中にインクリメントを入れると、意図しない結果になることがあります。
C#int i = 1;
int result = i++ + ++i * i++;
Console.WriteLine(result);
Console.WriteLine(i);
このコードは、どのタイミングで i が増えるのかを追うのが難しくなります。
動作を理解するために時間がかかるコードは、バグの原因になりやすいです。
次のように、処理を分けると読みやすくなります。
C#int i = 1;
int a = i;
i++;
i++;
int b = i;
int c = i;
i++;
int result = a + b * c;
Console.WriteLine(result);
Console.WriteLine(i);
複雑な計算では、インクリメントを式に埋め込まず、1行ずつ意味がわかるように書くのがおすすめです。
9. C#のインクリメント演算子に関するよくある質問
9-1. C#では++iとi++のどちらを使うべき?
単独で変数を1増やすだけなら、++i と i++ のどちらを使っても結果は同じです。
C#i++;
++i;
C#では、for 文の更新式などでは i++ がよく使われます。
C#for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
ただし、式の中で使う場合は動作が変わります。
C#int a = i++;
int b = ++i;
迷った場合は、式の中で使わず、処理を分けて書くと安全です。
C#i++;
int value = i;
9-2. インクリメント演算子は小数型にも使える?
はい、C#では double や decimal などの小数型にもインクリメント演算子を使えます。
C#double x = 1.5;
x++;
Console.WriteLine(x); // 2.5
C#decimal price = 10.5m;
price++;
Console.WriteLine(price); // 11.5
ただし、インクリメントは常に 1 増やす処理です。小数を 0.1 ずつ増やしたい場合は、+= を使います。
C#double x = 1.5;
x += 0.1;
9-3. for文ではなぜi++をよく使うの?
for 文では、ループが1回終わるたびにカウンターを1増やす処理がよく必要になります。
そのため、i++ がよく使われます。
C#for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
i++ は「iを1増やす」という意味が簡潔に伝わるため、カウンターの更新処理に向いています。
もちろん、次のように ++i を使っても、単独の更新式としては同じ結果になります。
C#for (int i = 0; i < 5; ++i)
{
Console.WriteLine(i);
}
実務では、チームやプロジェクトの書き方に合わせるのがよいでしょう。
9-4. i++はスレッドセーフ?
いいえ、通常の i++ はスレッドセーフではありません。
i++ は、値の読み取り、加算、書き込みという複数の処理から成り立っています。
複数スレッドが同時に同じ変数を更新すると、競合が発生して正しくカウントできないことがあります。
マルチスレッドで安全に値を増やしたい場合は、Interlocked.Increment を使います。
C#using System.Threading;
int counter = 0;
Interlocked.Increment(ref counter);
共有カウンターを複数スレッドから更新する場合は、counter++ ではなく、スレッドセーフな方法を選びましょう。
9-5. インクリメント演算子を使わない方がよい場面は?
インクリメント演算子は便利ですが、使わない方がよい場面もあります。
たとえば、次のような複雑な式の中では避けた方が安全です。
C#int result = i++ + ++i;
また、メソッドの引数に直接入れると、前置と後置の違いで読み手が混乱することがあります。
C#PrintNumber(i++);
可読性を重視するなら、次のように分けて書く方がおすすめです。
C#PrintNumber(i);
i++;
また、マルチスレッドで共有変数を更新する場合も、通常の i++ は避けるべきです。
C#Interlocked.Increment(ref counter);
インクリメント演算子は、単純なカウンター更新やループ処理で使うのが最もわかりやすい使い方です。
まとめ
C#のインクリメント演算子は、変数の値を1増やすための演算子です。
C#i++;
++i;
i++ は後置インクリメントで、現在の値を使った後に1増やします。
C#int i = 1;
int result = i++; // resultは1、iは2
++i は前置インクリメントで、先に1増やしてからその値を使います。
C#int i = 1;
int result = ++i; // resultは2、iは2
単独で使う場合は、i++ と ++i の結果は同じです。
C#i++;
++i;
しかし、代入式やメソッドの引数など、式の中で使うと結果が変わるため注意が必要です。
C#のインクリメント演算子は、for 文のカウンター、条件に一致した件数のカウント、配列やListのインデックス操作など、さまざまな場面で使われます。
一方で、複雑な式の中で多用すると読みづらくなり、バグの原因になります。また、マルチスレッド処理では通常の i++ は安全ではないため、Interlocked.Increment のような方法を使う必要があります。
初心者のうちは、まず次の3つを押さえておくとよいでしょう。
C#i++; // 1増やす
i += 1; // 1を加算する
i += 5; // 5を加算する
そして、++i と i++ の違いに迷う場合は、無理に式の中で使わず、処理を分けて書くことをおすすめします。
C#i++;
int value = i;
インクリメント演算子を正しく理解すると、C#のループ処理やカウンター処理がよりスムーズに書けるようになります。

