前に書いた記事の部分抜粋(C++) この後にC#コードがあるので慌てずに
main.cpp
# include <iostream>
# include <vector>
using namespace std;
void Print(vector<int> v)
{
for (auto& i : v)
{
cout << " " << i ;
}
cout << endl;
}
int main()
{
vector<int> vkeep{ 5, 5, 0, 5, 1 }; //5個
Print(v);
cout << "--- rfor内で自身のコンテナ追加 ------rforの値がバグる--------------" << endl;
for (auto& i : v)
{
cout << " " << i ;
if (i == 5)
v.emplace_back(123);
//v.push_back(123);
}
cout << endl << "-----5は3つあるので3つ123が増えないといけないが、バグっている-----" << endl;
Print(v);
}
実行結果、イテレータの位置がおかしくなり、エラーでなくバグる << 仕様らしい(デバッグビルド、もしくはデバッグ実行でエラーにしてほしいが・・・)
実行結果 :要素数も増えていなくて値も -572662307 という表示になる
--- rfor内で自身のコンテナ追加 ------rforの値がバグる--------------
5 -572662307 -572662307 -572662307 -572662307
これのC#バージョンを作る、ついでにラムダ記述方法も忘れたので確認
結論から言うと、foreach内での自身の配列(List)に要素数を増やすと実行時にエラーになる。
下記では、別配列(List)を用意して一旦こちらに追加して、まとめて追加(AddRange)している
main.cs
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
List<int> v = new List<int>(){ 5, 5, 0, 5, 1 };
var vpp = new List<int>();
foreach (var a in v)
{
//if (a == 5) v.Add(123); //error
if (a == 5) vpp.Add(123);
}
// ラムダで書いたバージョン
//v.ForEach(a => { if (a == 5) v.Add(123); }); //error
//v.ForEach(a => { if (a == 5) vpp.Add(123); });
v.AddRange(vpp); // v配列に appデータを増やす
foreach(var a in v)
{
Console.Write(" {0}",a);
}
// ラムダで書いたバージョン
//v.ForEach(a =>{
// Console.Write(" {0}",a);
//});
Console.WriteLine();
}
}
}
実行結果
Hello World!
5 5 0 5 1 123 123 123
ちなみにエラーコメントの行のコメントを外してもビルドエラーは出ない。実行時にエラーになる。
C# ではforeach で自身配列の変更をしてはいけないとなっており、
実行するとエラーが foreach の行 ですぐ出る。
C++では参照型を用い、rfor内の配列内の値の変更は可能だが、C#ではforeach 内ではそれすら許されない。
それは要素の増加に関しても同様のようだ。
※Visual Studio 2010時の C# では、foreachでの自身の値の変更はできて便利だった・・・時代の流れか