C# Collection was modified; enumeration operation may not execute
Possible Duplicate:
Collection was modified; enumeration operation may not execute
你好,
我正在创建一个项目估算程序,并收到以下错误:C集合已修改;枚举操作可能无法执行。
与使用此相关:我在全球范围内通过以下方式初步宣布该裁决:
1 |
包含此字典的下一个方法执行以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private void getFirstEstimation() { List<int> array = new List<int>(); string strConnection = ConfigurationSettings.AppSettings["ConnectionString"]; MySqlConnection connection = new MySqlConnection(strConnection); MySqlCommand command = connection.CreateCommand(); MySqlDataReader reader; command.CommandText ="SELECT idprojects FROM `test`.`projects` WHERE application_layers =" + applicationTiers; connection.Open(); reader = command.ExecuteReader(); while (reader.Read()) { array.Add(Convert.ToInt32(reader["idprojects"].ToString())); } foreach (int i in array) { rankings[i] = 15; } connection.Close(); } |
我在这里第二次这么叫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | private void getSecondEstimation() { Dictionary<int, string> sqltext = new Dictionary<int, string>(); Dictionary<int, int> valueForSql = new Dictionary<int, int>(); Dictionary<int, int> weightings = new Dictionary<int, int>(); sqltext.Add(1,"project_type"); valueForSql.Add(1, projectType); weightings.Add(1, 10); sqltext.Add(2,"application_domain"); valueForSql.Add(2, applicationDomain); weightings.Add(2, 8); sqltext.Add(3,"organisation_size"); valueForSql.Add(3, organizationSize); weightings.Add(3, 8); sqltext.Add(4,"no_of_locations"); valueForSql.Add(4, noOfLocations); weightings.Add(4, 7); sqltext.Add(5,"development_process"); valueForSql.Add(5, developmentProcess); weightings.Add(5, 6); sqltext.Add(6,"rules_engine"); valueForSql.Add(6, rulesEngine); weightings.Add(6, 5); sqltext.Add(7,"middleware"); valueForSql.Add(7, middleware); weightings.Add(7, 4); sqltext.Add(8,"location_of_development"); valueForSql.Add(8, locationOfDevelopment); weightings.Add(8, 3); sqltext.Add(9,"programming_language"); valueForSql.Add(9, programmingLanguage); weightings.Add(9, 3); sqltext.Add(10,"development_environment"); valueForSql.Add(10, developmentEnvironment); weightings.Add(10, 3); sqltext.Add(11,"backend"); valueForSql.Add(11, backend); weightings.Add(11, 3); sqltext.Add(12,"webserver"); valueForSql.Add(12, webServer); weightings.Add(12, 3); List<int> array = new List<int>(); string strConnection = ConfigurationSettings.AppSettings["ConnectionString"]; MySqlConnection connection = new MySqlConnection(strConnection); MySqlCommand command = connection.CreateCommand(); MySqlDataReader reader; for (int i = 1; i <= 12; i++) { command.CommandText ="SELECT idprojects FROM `test`.`projects` WHERE" + sqltext[i] +" =" + valueForSql[i]; connection.Open(); //int testInt; reader = command.ExecuteReader(); while (reader.Read()) { array.Add(Convert.ToInt32(reader["idprojects"].ToString())); } foreach (int a in array) { if (!rankings.ContainsKey(a)) { rankings[a] = 0; } rankings[a] = rankings[a] + weightings[i]; } connection.Close(); } } |
问题出现在代码的这个区域:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | private void getThirdEstimation() { ArrayList tempModuleHolder; string strConnection = ConfigurationSettings.AppSettings["ConnectionString"]; MySqlConnection connection = new MySqlConnection(strConnection); MySqlCommand command = connection.CreateCommand(); MySqlDataReader reader; int similarModules; foreach (KeyValuePair<int, int> kvp in rankings) { similarModules = 0; tempModuleHolder = new ArrayList(); command.CommandText ="SELECT id_modules FROM `test`.`modules_in_project` WHERE id_project =" + kvp.Key; connection.Open(); reader = command.ExecuteReader(); while (reader.Read()) { tempModuleHolder.Add(Convert.ToInt32(reader["id_modules"].ToString())); } foreach (int i in tempModuleHolder) { if(modules.Contains(i)) { similarModules++; } } if((double)(similarModules/modules.Count)>0.6) { //kvp.Value = kvp.Value + 4; rankings[kvp.Key] = rankings[kvp.Key] + 4; } connection.Close(); } } |
如果有任何帮助解决问题,我们将不胜感激。
在迭代期间,不能修改使用foreach迭代的任何集合。
因此,当您在排名上运行foreach时,您不能修改它的元素、添加新的元素或删除任何元素。
该错误确切地告诉您问题是什么(在调试器中运行或读取堆栈跟踪将确切地告诉您问题在哪里):
C# Collection was modified; enumeration operation may not execute.
你的问题是循环
1 2 3 | foreach (KeyValuePair<int, int> kvp in rankings) { // } |
其中修改了集合
1 | rankings[kvp.Key] = rankings[kvp.Key] + 4; |
在进入循环之前,请添加以下行:
1 |
将违规行替换为
1 | listOfRankingsToModify.Add(kvp.Key); |
在你退出循环之后
1 2 3 | foreach(var key in listOfRankingsToModify) { rankings[key] = rankings[key] + 4; } |
也就是说,记录需要进行的更改,并在不迭代需要修改的集合的情况下进行更改。
正如其他人指出的,您正在修改一个正在迭代的集合,这就是导致错误的原因。违规代码如下:
1 2 3 4 5 6 7 8 9 | foreach (KeyValuePair<int, int> kvp in rankings) { ..... if((double)(similarModules/modules.Count)>0.6) { rankings[kvp.Key] = rankings[kvp.Key] + 4; // <--- This line is the problem } ..... |
上面代码中不明显的是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | { IEnumerator<int> e = ((IEnumerable<int>)values).GetEnumerator(); // <-- This // is where the Enumerator // comes from. try { int m; // OUTSIDE THE ACTUAL LOOP in C# 4 and before, inside the loop in 5 while(e.MoveNext()) { // loop code goes here } } finally { if (e != null) ((IDisposable)e).Dispose(); } } |
如果您在msdn文档中查找IEnumerable(这是
Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
这使我们回到错误消息的状态,而其他答案的状态,您正在修改基础集合。
我怀疑错误是由以下原因引起的:
1 | foreach (KeyValuePair<int, int> kvp in rankings) |
排名是一本字典,它是IEnumerable。通过在foreach循环中使用它,可以指定要延迟地从字典中获取每个keyValuePair。也就是说,在循环再次迭代之前,不会返回下一个keyValuePair。
但你在修改循环中的字典:
1 | rankings[kvp.Key] = rankings[kvp.Key] + 4; |
这是不允许的…所以你得到了例外。
你可以这么做
1 | foreach (KeyValuePair<int, int> kvp in rankings.ToArray()) |
问题在于您执行的位置:
1 | rankings[kvp.Key] = rankings[kvp.Key] + 4; |
不能在foreach循环中修改正在迭代的集合.forEach循环要求循环在迭代期间是不可变的。
相反,使用一个标准的"for"循环,或者创建一个新的循环,这个循环是一个副本,并在更新原始循环的同时对其进行迭代。