C# foreachの使い方を初心者向けに解説|配列・List・Dictionaryのループ処理と注意点

はじめに

C#で配列やList、Dictionaryなどのデータを順番に処理したいときによく使うのがforeach文です。

foreachを使うと、コレクションの中にある要素を1つずつ取り出して処理できます。たとえば、名前の一覧を画面に表示したり、数値の合計を計算したり、Dictionaryのキーと値を一覧表示したりできます。

この記事では、C#初心者向けにforeachの基本構文、配列・List・Dictionaryでの使い方、breakcontinueとの組み合わせ、よくあるエラーと対処法までわかりやすく解説します。

1. C#のforeachとは?初心者向けに基本を解説

1-1. foreachは配列やListなどの要素を順番に取り出す構文

C#のforeachは、配列やListなどのコレクションに入っている要素を、先頭から順番に取り出して処理するための構文です。

たとえば、次のような名前の配列があるとします。

C#
string[] names = { "田中", "佐藤", "鈴木" };

この配列の中身をすべて表示したい場合、foreachを使うと次のように書けます。

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

実行結果は次のとおりです。

C#
田中
佐藤
鈴木

foreachでは、namesの中にある要素が1つずつnameに代入され、ブロック内の処理が繰り返されます。

1-2. for文との違い:インデックス不要でシンプルに書ける

C#で繰り返し処理を書く方法には、for文もあります。

C#
string[] names = { "田中", "佐藤", "鈴木" };

for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}

for文では、iというインデックス番号を使って配列の要素を取り出します。

一方、foreachではインデックス番号を意識せずに書けます。

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

要素を先頭から順番に処理するだけであれば、foreachのほうが読みやすく、初心者にも理解しやすい書き方です。

1-3. foreachが使える主なデータ型

foreachは、複数の要素を持つさまざまなデータ型に対して使えます。

代表的なものは次のとおりです。

C#
string[] array = { "A", "B", "C" };

List<string> list = new List<string> { "Apple", "Banana", "Orange" };

Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 }
};

配列、List<T>Dictionary<TKey, TValue>のように、複数のデータをまとめて扱う型ではforeachがよく使われます。

また、HashSet<T>Queue<T>Stack<T>などのコレクションでもforeachを使用できます。

2. C# foreachの基本構文と書き方

2-1. foreach文の基本構文

foreach文の基本構文は次のとおりです。

C#
foreach (要素の型 変数名 in コレクション)
{
// 繰り返し実行したい処理
}

たとえば、文字列の配列を処理する場合は次のようになります。

C#
string[] fruits = { "Apple", "Banana", "Orange" };

foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}

このコードでは、fruitsの中にある要素が1つずつfruitに入ります。

1回目のループではfruit"Apple"、2回目では"Banana"、3回目では"Orange"が入ります。

2-2. varを使った書き方

C#では、型を明示せずにvarを使って書くこともできます。

C#
var fruits = new List<string> { "Apple", "Banana", "Orange" };

foreach (var fruit in fruits)
{
Console.WriteLine(fruit);
}

varを使うと、C#が右側のコレクションから型を自動的に判断してくれます。

この例では、fruitsList<string>なので、fruitstring型として扱われます。

varは便利ですが、初心者のうちは「この変数には何の型が入るのか」を意識しながら使うと理解しやすくなります。

2-3. 型を明示して書く方法

型を明示して書く場合は、次のように記述します。

C#
List<int> numbers = new List<int> { 10, 20, 30 };

foreach (int number in numbers)
{
Console.WriteLine(number);
}

この例では、numbersの各要素はint型なので、foreachの変数もint numberと書いています。

型を明示すると、コードを読んだときに「どの型のデータを扱っているのか」がわかりやすくなります。

初心者のうちは、最初は型を明示して書き、慣れてきたらvarを使うとよいでしょう。

2-4. foreach内で実行する処理の書き方

foreachの中では、取り出した要素を使ってさまざまな処理ができます。

たとえば、要素を表示するだけでなく、条件分岐や計算もできます。

C#
int[] numbers = { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
if (number % 2 == 0)
{
Console.WriteLine(number + "は偶数です");
}
}

実行結果は次のとおりです。

C#
2は偶数です
4は偶数です

このように、foreachif文や計算処理と組み合わせて使うことができます。

3. 配列をforeachでループ処理する方法

3-1. 文字列配列をforeachで表示する例

配列は、同じ型のデータを複数まとめて扱うための基本的なデータ型です。

文字列配列をforeachで処理する例を見てみましょう。

C#
string[] colors = { "Red", "Blue", "Green" };

foreach (string color in colors)
{
Console.WriteLine(color);
}

実行結果は次のようになります。

C#
Red
Blue
Green

配列の中にある文字列が、先頭から順番に取り出されて表示されます。

3-2. 数値配列をforeachで合計する例

foreachは、数値の合計を計算するときにも便利です。

C#
int[] scores = { 80, 90, 75, 60 };

int total = 0;

foreach (int score in scores)
{
total += score;
}

Console.WriteLine("合計点: " + total);

実行結果は次のとおりです。

C#
合計点: 305

foreachで1つずつ点数を取り出し、totalに加算しています。

平均点を求めたい場合は、合計を配列の要素数で割ります。

C#
double average = (double)total / scores.Length;

Console.WriteLine("平均点: " + average);

3-3. 配列の要素数が変わっても対応しやすい理由

foreachは、配列の要素数を自分で指定する必要がありません。

たとえば、次のように配列の要素が増えても、foreachの書き方は変わりません。

C#
string[] animals = { "Dog", "Cat", "Rabbit", "Bird" };

foreach (string animal in animals)
{
Console.WriteLine(animal);
}

for文ではLengthを使って回数を指定しますが、foreachではコレクションの中身を自動的に最後まで処理してくれます。

そのため、要素数が変わる可能性がある場合でも、シンプルで安全に書きやすいのがメリットです。

4. Listをforeachでループ処理する方法

4-1. List<string>をforeachで順番に取り出す

List<T>は、C#でよく使われる可変長のコレクションです。

配列と違い、要素の追加や削除がしやすいという特徴があります。

C#
List<string> fruits = new List<string>
{
"Apple",
"Banana",
"Orange"
};

foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}

実行結果は次のようになります。

C#
Apple
Banana
Orange

List<string>の各要素が、順番にfruitへ代入されます。

4-2. List<int>を使った計算処理の例

List<int>を使って、数値の合計を求める例です。

C#
List<int> prices = new List<int> { 100, 200, 300 };

int total = 0;

foreach (int price in prices)
{
total += price;
}

Console.WriteLine("合計金額: " + total);

実行結果は次のとおりです。

C#
合計金額: 600

foreachを使うことで、Listの中にある数値を1つずつ取り出して計算できます。

4-3. Listの要素を検索・条件分岐する方法

Listの中から条件に合う要素だけを処理したい場合は、foreachif文を組み合わせます。

C#
List<int> numbers = new List<int> { 3, 8, 12, 5, 20 };

foreach (int number in numbers)
{
if (number >= 10)
{
Console.WriteLine(number);
}
}

実行結果は次のとおりです。

C#
12
20

このコードでは、number >= 10の条件を満たす要素だけを表示しています。

文字列の検索にも使えます。

C#
List<string> names = new List<string> { "Tanaka", "Sato", "Suzuki" };

foreach (string name in names)
{
if (name.StartsWith("S"))
{
Console.WriteLine(name);
}
}

実行結果は次のようになります。

C#
Sato
Suzuki

4-4. Listの要素をforeach中に削除・追加する際の注意点

foreachでListを処理している最中に、そのListへ要素を追加したり削除したりすると、エラーになることがあります。

次のコードはよくない例です。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
if (number % 2 == 0)
{
numbers.Remove(number);
}
}

このようにforeachで回している最中にRemoveすると、実行時に例外が発生する可能性があります。

削除したい場合は、RemoveAllを使う方法が簡単です。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

numbers.RemoveAll(number => number % 2 == 0);

foreach (int number in numbers)
{
Console.WriteLine(number);
}

実行結果は次のとおりです。

C#
1
3
5

または、後ろからfor文で削除する方法もあります。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}

Listの要素を削除・追加したい場合は、foreachではなく、目的に合った別の方法を使うようにしましょう。

5. Dictionaryをforeachでループ処理する方法

5-1. Dictionaryのキーと値をforeachで取り出す

Dictionary<TKey, TValue>は、キーと値をセットで管理するコレクションです。

たとえば、名前と点数を管理する場合に使えます。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

このDictionaryをforeachで処理すると、キーと値をまとめて取り出せます。

C#
foreach (var score in scores)
{
Console.WriteLine(score.Key + ": " + score.Value);
}

実行結果は次のとおりです。

C#
田中: 80
佐藤: 90
鈴木: 75

score.Keyでキー、score.Valueで値を取得できます。

5-2. KeyValuePairを使った基本的な書き方

Dictionaryをforeachで処理するとき、各要素はKeyValuePair<TKey, TValue>として扱われます。

型を明示して書くと、次のようになります。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

foreach (KeyValuePair<string, int> item in scores)
{
Console.WriteLine(item.Key + "さんの点数は" + item.Value + "点です");
}

実行結果は次のとおりです。

C#
田中さんの点数は80点です
佐藤さんの点数は90点です
鈴木さんの点数は75点です

varを使うと短く書けます。

C#
foreach (var item in scores)
{
Console.WriteLine(item.Key + "さんの点数は" + item.Value + "点です");
}

初心者のうちは、Dictionaryのforeachでは「1件分のデータはキーと値のペアになる」と覚えておくとよいでしょう。

5-3. Keysだけをループする方法

Dictionaryのキーだけを取り出したい場合は、Keysプロパティを使います。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

foreach (string name in scores.Keys)
{
Console.WriteLine(name);
}

実行結果は次のとおりです。

C#
田中
佐藤
鈴木

キーの一覧だけが必要な場合は、scores.Keysforeachで回すとシンプルです。

5-4. Valuesだけをループする方法

Dictionaryの値だけを取り出したい場合は、Valuesプロパティを使います。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

foreach (int score in scores.Values)
{
Console.WriteLine(score);
}

実行結果は次のとおりです。

C#
80
90
75

値だけを合計することもできます。

C#
int total = 0;

foreach (int score in scores.Values)
{
total += score;
}

Console.WriteLine("合計点: " + total);

Dictionaryでは、キーと値の両方が必要な場合はDictionary本体をforeachし、キーだけならKeys、値だけならValuesを使いましょう。

6. foreachで使える便利な制御文

6-1. breakでループを途中終了する

breakを使うと、foreachのループを途中で終了できます。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木", "山田" };

foreach (string name in names)
{
if (name == "鈴木")
{
Console.WriteLine("鈴木さんを見つけました");
break;
}

Console.WriteLine(name);
}

このコードでは、name"鈴木"になった時点でbreakが実行され、ループが終了します。

実行結果は次のようになります。

C#
田中
佐藤
鈴木さんを見つけました

特定の要素が見つかったら、それ以上処理する必要がない場合にbreakは便利です。

6-2. continueで処理をスキップする

continueを使うと、現在のループ処理だけをスキップして、次の要素へ進めます。

C#
int[] numbers = { 1, 2, 3, 4, 5 };

foreach (int number in numbers)
{
if (number % 2 == 0)
{
continue;
}

Console.WriteLine(number);
}

実行結果は次のとおりです。

C#
1
3
5

このコードでは、偶数の場合にcontinueが実行され、Console.WriteLine(number);がスキップされます。

そのため、奇数だけが表示されます。

6-3. if文と組み合わせて条件に合う要素だけ処理する

foreachif文と組み合わせることで、条件に合う要素だけを処理できます。

C#
List<int> scores = new List<int> { 45, 70, 85, 30, 90 };

foreach (int score in scores)
{
if (score >= 60)
{
Console.WriteLine(score + "点は合格です");
}
}

実行結果は次のとおりです。

C#
70点は合格です
85点は合格です
90点は合格です

条件に合うデータだけ表示したい場合、foreachif文の組み合わせは非常によく使われます。

7. foreachを使うときの注意点

7-1. foreach中にコレクションを変更するとエラーになる

foreachでコレクションを処理している最中に、そのコレクションの要素を追加・削除すると、エラーになることがあります。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
if (name == "佐藤")
{
names.Remove(name);
}
}

このようなコードは、実行時に次のような例外が発生する可能性があります。

C#
InvalidOperationException: Collection was modified; enumeration operation may not execute.

対処法としては、次のような方法があります。

C#
names.RemoveAll(name => name == "佐藤");

または、コピーしたListをforeachする方法もあります。

C#
foreach (string name in names.ToList())
{
if (name == "佐藤")
{
names.Remove(name);
}
}

ただし、ToList()を使うには次のusingが必要です。

C#
using System.Linq;

7-2. foreachでは基本的にインデックス番号を直接扱わない

foreachは、要素を順番に取り出すための構文なので、基本的にインデックス番号を直接扱いません。

C#
string[] names = { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
Console.WriteLine(name);
}

このコードでは、現在何番目の要素を処理しているかはわかりません。

インデックス番号が必要な場合は、for文を使うほうが自然です。

C#
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(i + ": " + names[i]);
}

また、foreachでインデックスを使いたい場合は、自分でカウンター変数を用意します。

C#
int index = 0;

foreach (string name in names)
{
Console.WriteLine(index + ": " + name);
index++;
}

7-3. 要素そのものを書き換えたい場合の注意点

foreachで取り出した変数に対して、直接代入することはできません。

次のコードはエラーになります。

C#
int[] numbers = { 1, 2, 3 };

foreach (int number in numbers)
{
number = number * 2;
}

foreachの変数numberは読み取り専用のように扱われるため、直接書き換えることはできません。

配列やListの要素そのものを書き換えたい場合は、インデックスを使えるfor文が向いています。

C#
int[] numbers = { 1, 2, 3 };

for (int i = 0; i < numbers.Length; i++)
{
numbers[i] = numbers[i] * 2;
}

一方、参照型のオブジェクトであれば、オブジェクトのプロパティを変更できる場合があります。

C#
class User
{
public string Name { get; set; }
public int Age { get; set; }
}

List<User> users = new List<User>
{
new User { Name = "田中", Age = 20 },
new User { Name = "佐藤", Age = 25 }
};

foreach (User user in users)
{
user.Age += 1;
}

この場合、user自体に別のオブジェクトを代入するのではなく、user.Ageというプロパティを変更しています。

7-4. nullのコレクションをforeachすると例外が発生する

foreachの対象がnullの場合、NullReferenceExceptionが発生します。

C#
List<string> names = null;

foreach (string name in names)
{
Console.WriteLine(name);
}

このコードは実行時にエラーになります。

対処法として、foreachの前にnullチェックを行います。

C#
List<string> names = null;

if (names != null)
{
foreach (string name in names)
{
Console.WriteLine(name);
}
}

または、空のListで初期化しておく方法もあります。

C#
List<string> names = new List<string>();

foreach (string name in names)
{
Console.WriteLine(name);
}

空のListに対してforeachしても、エラーにはならず、単に何も処理されません。

8. foreachとfor文の使い分け

8-1. foreachが向いているケース

foreachが向いているのは、コレクションの要素を先頭から順番に処理したい場合です。

たとえば、次のようなケースです。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
Console.WriteLine(name);
}

全要素を表示する、合計を計算する、条件に合う要素を探すといった処理では、foreachが読みやすく便利です。

特に、インデックス番号が不要な処理ではforeachを使うとコードがシンプルになります。

8-2. for文が向いているケース

for文が向いているのは、インデックス番号を使いたい場合や、要素を書き換えたい場合です。

たとえば、配列の各要素を2倍にしたい場合は、for文が適しています。

C#
int[] numbers = { 1, 2, 3 };

for (int i = 0; i < numbers.Length; i++)
{
numbers[i] *= 2;
}

また、後ろから順番にListの要素を削除したい場合にもfor文が使われます。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}

8-3. インデックスが必要な場合の書き方

インデックス番号が必要な場合は、基本的にはfor文を使います。

C#
string[] names = { "田中", "佐藤", "鈴木" };

for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(i + "番目: " + names[i]);
}

foreachでインデックスを使いたい場合は、カウンター変数を用意します。

C#
int index = 0;

foreach (string name in names)
{
Console.WriteLine(index + "番目: " + name);
index++;
}

また、LINQのSelectを使う方法もあります。

C#
foreach (var item in names.Select((name, index) => new { name, index }))
{
Console.WriteLine(item.index + "番目: " + item.name);
}

この方法を使うには、次のusingが必要です。

C#
using System.Linq;

初心者のうちは、インデックスが必要ならfor文、不要ならforeachと考えるとわかりやすいです。

8-4. 可読性を重視するならforeachが便利

可読性を重視する場合、foreachはとても便利です。

C#
foreach (string name in names)
{
Console.WriteLine(name);
}

このコードは、「namesの中のnameを1つずつ処理する」という意味が直感的にわかります。

一方、for文はインデックスの初期化、条件式、増加処理を書く必要があります。

C#
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
}

どちらも正しい書き方ですが、単純に全要素を順番に処理するだけなら、foreachのほうが読みやすいことが多いです。

9. foreachでよくあるエラーと対処法

9-1. Collection was modifiedエラーの原因と解決策

foreachでよくあるエラーの1つが、コレクションを変更したときに発生するエラーです。

C#
List<int> numbers = new List<int> { 1, 2, 3, 4 };

foreach (int number in numbers)
{
if (number == 2)
{
numbers.Remove(number);
}
}

このコードでは、foreachnumbersを処理している最中に、同じnumbersから要素を削除しています。

その結果、次のようなエラーが発生することがあります。

C#
Collection was modified; enumeration operation may not execute.

解決策としては、RemoveAllを使います。

C#
numbers.RemoveAll(number => number == 2);

または、コピーを作ってループします。

C#
foreach (int number in numbers.ToList())
{
if (number == 2)
{
numbers.Remove(number);
}
}

大量のデータを扱う場合は、コピーによるメモリ使用量にも注意しましょう。

9-2. NullReferenceExceptionが出る原因と対処法

foreachの対象がnullの場合、NullReferenceExceptionが発生します。

C#
List<string> names = null;

foreach (string name in names)
{
Console.WriteLine(name);
}

対処法は、nullチェックを行うことです。

C#
if (names != null)
{
foreach (string name in names)
{
Console.WriteLine(name);
}
}

また、変数を宣言するときに空のListで初期化しておくと安全です。

C#
List<string> names = new List<string>();

C#では、nullの可能性があるコレクションをforeachする前に、必ず値が入っているか確認しましょう。

9-3. 型が合わない場合のエラー

foreachで指定した型と、コレクションの要素の型が合わない場合はエラーになります。

たとえば、List<int>の要素をstringとして取り出そうとすると問題になります。

C#
List<int> numbers = new List<int> { 1, 2, 3 };

foreach (string number in numbers)
{
Console.WriteLine(number);
}

numbersの要素はint型なので、foreachの変数もintにする必要があります。

C#
foreach (int number in numbers)
{
Console.WriteLine(number);
}

型がわかりにくい場合は、varを使うとC#が自動で型を推論してくれます。

C#
foreach (var number in numbers)
{
Console.WriteLine(number);
}

ただし、varを使う場合でも、実際にどの型が入っているのかを理解しておくことが大切です。

9-4. Dictionaryのキー・値の取り出し方を間違えた場合

Dictionaryをforeachすると、1つずつ取り出される要素はキーと値のペアです。

次のように、Dictionaryをそのままstringとして受け取ることはできません。

C#
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 }
};

foreach (string score in scores)
{
Console.WriteLine(score);
}

正しくは、KeyValuePairまたはvarを使います。

C#
foreach (var score in scores)
{
Console.WriteLine(score.Key + ": " + score.Value);
}

キーだけを取り出したい場合は、Keysを使います。

C#
foreach (string name in scores.Keys)
{
Console.WriteLine(name);
}

値だけを取り出したい場合は、Valuesを使います。

C#
foreach (int point in scores.Values)
{
Console.WriteLine(point);
}

Dictionaryでは、キーと値のどちらを使いたいのかを意識して書くことが大切です。

10. C# foreachの実践サンプルコード

10-1. 配列の全要素を表示するサンプル

まずは、配列の全要素を表示する基本的なサンプルです。

C#
using System;

class Program
{
static void Main()
{
string[] languages = { "C#", "Java", "Python", "JavaScript" };

foreach (string language in languages)
{
Console.WriteLine(language);
}
}
}

実行結果は次のとおりです。

C#
C#
Java
Python
JavaScript

配列の中にある要素が、先頭から順番に表示されます。

10-2. Listから条件に一致する要素を表示するサンプル

次に、Listの中から条件に一致する要素だけを表示するサンプルです。

C#
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<int> scores = new List<int> { 45, 80, 60, 30, 95 };

foreach (int score in scores)
{
if (score >= 60)
{
Console.WriteLine(score + "点: 合格");
}
}
}
}

実行結果は次のとおりです。

C#
80: 合格
60: 合格
95: 合格

if文を使うことで、条件に合う要素だけを処理できます。

10-3. Dictionaryの内容を一覧表示するサンプル

Dictionaryのキーと値を一覧表示するサンプルです。

C#
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "田中", 80 },
{ "佐藤", 90 },
{ "鈴木", 75 }
};

foreach (var item in scores)
{
Console.WriteLine(item.Key + "さん: " + item.Value + "点");
}
}
}

実行結果は次のとおりです。

C#
田中さん: 80
佐藤さん: 90
鈴木さん: 75

Dictionaryでは、item.Keyでキー、item.Valueで値を取得します。

10-4. break・continueを使ったサンプル

最後に、breakcontinueを使ったサンプルです。

C#
using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };

foreach (int number in numbers)
{
if (number == 2)
{
continue;
}

if (number == 5)
{
break;
}

Console.WriteLine(number);
}
}
}

実行結果は次のとおりです。

C#
1
3
4

number2のときはcontinueで表示処理をスキップします。

number5のときはbreakでループを終了します。

このように、breakcontinueを使うと、ループの流れを細かく制御できます。

11. C# foreachに関するよくある質問

11-1. foreachでインデックスを取得できますか?

foreach自体には、インデックス番号を自動で取得する機能はありません。

インデックスが必要な場合は、カウンター変数を用意します。

C#
string[] names = { "田中", "佐藤", "鈴木" };

int index = 0;

foreach (string name in names)
{
Console.WriteLine(index + ": " + name);
index++;
}

実行結果は次のとおりです。

C#
0: 田中
1: 佐藤
2: 鈴木

よりシンプルにインデックスを扱いたい場合は、for文を使うのがおすすめです。

C#
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(i + ": " + names[i]);
}

11-2. foreach中にListの要素を削除できますか?

基本的には、foreach中に同じListの要素を削除するのは避けるべきです。

次のようなコードはエラーの原因になります。

C#
foreach (int number in numbers)
{
if (number % 2 == 0)
{
numbers.Remove(number);
}
}

削除したい場合は、RemoveAllを使うと安全です。

C#
numbers.RemoveAll(number => number % 2 == 0);

または、後ろからfor文で削除します。

C#
for (int i = numbers.Count - 1; i >= 0; i--)
{
if (numbers[i] % 2 == 0)
{
numbers.RemoveAt(i);
}
}

「表示するだけ」「条件に合うものを探すだけ」ならforeach、「要素を削除・変更する」ならfor文や専用メソッドを検討しましょう。

11-3. foreachとLINQはどう使い分けますか?

foreachは、要素を1つずつ取り出して処理を実行したいときに使います。

C#
foreach (int number in numbers)
{
Console.WriteLine(number);
}

一方、LINQは、データの抽出、変換、並び替え、集計などを簡潔に書きたいときに便利です。

C#
var evenNumbers = numbers.Where(number => number % 2 == 0);

条件に合う要素を取得するだけならLINQ、取得した要素に対して複数の処理を行うならforeachがわかりやすい場合があります。

たとえば、偶数だけを表示する場合は、LINQとforeachを組み合わせることもできます。

C#
foreach (int number in numbers.Where(number => number % 2 == 0))
{
Console.WriteLine(number);
}

初心者のうちは、まずforeachで処理の流れを理解し、慣れてきたらLINQを使うとよいでしょう。

11-4. UnityのC#でもforeachは使えますか?

はい、UnityのC#でもforeachは使えます。

たとえば、GameObjectのListを順番に処理する場合に使えます。

C#
using System.Collections.Generic;
using UnityEngine;

public class Sample : MonoBehaviour
{
public List<GameObject> enemies;

void Start()
{
foreach (GameObject enemy in enemies)
{
Debug.Log(enemy.name);
}
}
}

Unityでも、配列やListを順番に処理したい場面は多いため、foreachはよく使われます。

ただし、Unityのパフォーマンスが重要な処理、特に毎フレーム実行されるUpdate内で大量のデータを処理する場合は、処理コストにも注意が必要です。

通常の規模であればforeachは問題なく使えますが、大量のオブジェクトを頻繁に処理する場合は、for文やデータ構造の見直しも検討しましょう。

まとめ

C#のforeachは、配列、List、Dictionaryなどのコレクションを順番に処理するための便利な構文です。

基本構文は次の形です。

C#
foreach (要素の型 変数名 in コレクション)
{
// 処理
}

配列では要素を1つずつ取り出して表示したり、数値の合計を計算したりできます。

C#
int[] numbers = { 1, 2, 3 };

foreach (int number in numbers)
{
Console.WriteLine(number);
}

Listでも同じように使えます。

C#
List<string> names = new List<string> { "田中", "佐藤", "鈴木" };

foreach (string name in names)
{
Console.WriteLine(name);
}

Dictionaryでは、キーと値をセットで取り出せます。

C#
foreach (var item in scores)
{
Console.WriteLine(item.Key + ": " + item.Value);
}

foreachは、インデックス番号が不要なループ処理に向いています。

一方で、要素の削除・追加、インデックスを使った処理、要素そのものの書き換えには注意が必要です。

使い分けの目安は次のとおりです。

C#
// 全要素を順番に処理するならforeach
foreach (var item in items)
{
Console.WriteLine(item);
}

// インデックスが必要ならfor
for (int i = 0; i < items.Count; i++)
{
Console.WriteLine(items[i]);
}

C#初心者の方は、まず配列やListを使った簡単なforeachから練習してみましょう。慣れてくると、Dictionaryや条件分岐、breakcontinueとの組み合わせも自然に使えるようになります。