10265


下記コードのForEachを使った処理で①~④の処理中にDownLoadDataListのカウントが変化すると  
次のMoveNextでエラーになるのでしょうか？

ループが１週した後に、ForEachまで来ると下記のエラーがでます。  
**InvalidOperationException: Collection was modified; enumeration operation
may not execute.**

[code]

    foreach (DownLoadData downloaddata in DownLoadDataList)
    {
        ①処理・・・・・・
        ②処理・・・・・・
        ③処理・・・・・・
        ④処理・・・・・・
    }
    
[/code]

DownLoadDataListはList＜DownLoadData＞で定義されています。

環境はUnity5.0.1f1 .Netは2.0です。


CC BY-SA 3.0
2015-05-13T10:04:57.493
10119
2015-05-16T16:08:56.850
5261
question
c# unity3d .net
ForEach文で中身の処理中に母集合側が変化するとMoveNextでエラーになる？


仕様通りの動作です。リストのバージョンが変わるとそれ以前に`List<T>.GetEnumerator()`の返した`IEnumerator`は無効になります。

要件に合わせて`List<T>.ToArray()`や`Enumerable.ToList()`でリストを複製するようにしてください。


CC BY-SA 3.0
2015-05-13T10:29:24.153
10120
2015-05-13T10:29:24.153
5750
10119
answer


仕様上、foreachの処理中にコレクションに追加・削除が発生すると、 **InvalidOperationException** が発生します。  
正確には、GetEnumeratorメソッドがそのように実装されています。

これを回避する方法は、いくつかあります。  
代表的なのが追加、削除、foreachなどの操作を行うとき、コレクション全体をlockする手法です。  
しかし、デッドロックを引き起こす可能性があります。  
lockの管理(排他制御)は、細心の注意を払わなければなりません。

第二の方法として **System.Collections.Concurrent** 名前空間にあるコレクションを使用する手法です。  
Concurrentなコレクションは、lock不要なコレクションです。  
コレクションをforeachすると、そのコレクションのスナップショットを使用してforeachが行われます。  
そのため、追加、削除が発生し、コレクションが変更されても、例外を発生しません。  
しかし、Concurrent系のコレクションは、インデクサによるアクセスができません。

第三の方法として、nugetから追加が必要となりますが、  
**System.Collections.Immutable** 名前空間のコレクションを使用する手法です。  
追加、削除などの操作は、新しいコレクションに反映され、元のコレクションに影響を与えません。  
しかし、コレクション全体を複製するため、頻繁な変更が発生するとパフォーマンスに影響を与えることがあります。


CC BY-SA 3.0
2015-05-16T16:08:56.850
10265
2015-05-16T16:08:56.850
2207
10119
answer