Code Fix

中級

Collection was modified の原因と直し方

foreach中にList等のコレクションの要素数を変えると発生します。反復子(イテレータ)が内部状態の不整合を検知する仕組みです。

エラーメッセージの読み方

Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
System
名前空間 — System なら標準の基本例外です
InvalidOperationException
例外クラス — 何が起きたか。ここを検索するのが最短です
Collection was modified; enumeration operation may not execute.
詳細メッセージ — どの値が問題だったか
at Program.Main(String[] args) in Program.cs:line 4
発生箇所 — スタックトレースの先頭行

このエラーが出る典型パターン

パターン1

 1  class Program {
 2      static void Main(string[] args) {
 3          var nums = new System.Collections.Generic.List<int> { 1, 2, 3 };
 4          foreach (int n in nums) {
 5              if (n == 2) {
 6                  nums.Remove(n)             ;
                                 ^
 7              }
 8          }
 9      }
10  }
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at Program.Main(String[] args) in Program.cs:line 4

foreach中にコレクションの要素数を変えると、内部の反復子が不整合を検知して例外を投げます。

直し方: nums.Remove(n)System.Console.WriteLine(n) にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  class Program {
 2      static void Main(string[] args) {
 3          var nums = new System.Collections.Generic.List<int> { 1, 2, 3 };
 4          foreach (int n in nums) {
 5              if (n == 1) {
 6                  nums.Add(n * 10)                ;
                                    ^
 7              }
 8          }
 9      }
10  }
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at Program.Main(String[] args) in Program.cs:line 4

要素を追加する場合も同じです。反復中はコレクションの形を変えてはいけません。

直し方: nums.Add(n * 10)System.Console.WriteLine(n * 10) にします。

この問題を解いてみる →

パターン3

 1  class Program {
 2      static void Main(string[] args) {
 3          var nums = new System.Collections.Generic.List<int> { 1, 2, 3 };
 4          foreach (int n in nums) {
 5              if (n == 3) {
 6                  nums.RemoveAt(0)                 ;
                                    ^
 7              }
 8          }
 9      }
10  }
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at Program.Main(String[] args) in Program.cs:line 4

RemoveAtでインデックス指定で消す場合も同様です。安全に消したいならToList()でコピーしてから反復します。

直し方: nums.RemoveAt(0)System.Console.WriteLine(nums[0]) にします。

この問題を解いてみる →

よくある誤解

forループなら添字で直接アクセスするので気づきにくいですが、foreachは内部で反復子を使っており、反復中の追加・削除に非常に敏感です。

まとめ

Collection was modifiedは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)