はじめに
C#(.Net)でforeachを回す方法として、素直にforeachを使用する方法とSystem.Collections.Generic.ListのForEachを使う方法の2通りがあります。
var hogeList = new List<int>();
//書き方1
foreach (var hoge in hogeList) {
//処理
}
//書き方2
hogeList.ForEach(hoge => {
//処理
});
書き方2の方はbreak・continueが使えず、returnを使うことでcontinue相当の処理をすることができます。
というのを人に説明しながら、そもそも何でbreak・continueが使えないんだ?何でreturnを使うんだ? ということが気になったので、このようになっている理由を確認します。
ForEachの実装を確認
MicrosoftがSystem.Collections.Generic.Listのコードを公開しているので、以下からForEachの実装を確認します。
ForEachの実装部分を引用します。
public void ForEach(Action<T> action) {
//略
for(int i = 0 ; i < _size; i++) {
//略
action(_items[i]);
}
//略
}
引数部分を見てみると、Actionを渡していることがわかります。そしてそのActionをListの各要素に対して実行しています。つまり、書き方2の処理部分はforeachのループの中身ではなく、メソッドの一部を記述していることになります。
以上より、最初の問題を納得いく形で理解できるようになりました。
- 書き方2の処理部分はメソッドの一部であり、foreachの一部ではないため、break・continueを使用できない
- 書き方2の処理部分はメソッドの一部であるため、returnすることで処理を終了できる。この際、ForEachの実装としてはメソッドを各要素に対して実行しているだけなので、returnすることはその要素への実行の終了=continue相当となり、break相当のことができるような実装はない