0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#foreachで自身の配列にデータを追加する

Last updated at Posted at 2019-12-14

前に書いた記事の部分抜粋(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 の行 ですぐ出る。

image.png

C++では参照型を用い、rfor内の配列内の値の変更は可能だが、C#ではforeach 内ではそれすら許されない。
それは要素の増加に関しても同様のようだ。

※Visual Studio 2010時の C# では、foreachでの自身の値の変更はできて便利だった・・・時代の流れか

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?