可能重复:
Collection was modified; enumeration operation may not execute
你好,
我正在创建一个项目估算程序,并收到以下错误:C#Collection已修改;枚举操作可能无法执行。
与使用此相关: 我最初在全球范围内声明了这一点:
Dictionary<int, int> rankings = new Dictionary<int, int>();
包含此词典的Next方法执行以下操作:
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();
}
我在这里第二次打电话:
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();
}
}
问题出现在代码的这个区域:
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();
}
}
非常感谢任何有关问题所在的帮助
答案 0 :(得分:89)
使用foreach迭代的任何集合在迭代期间都不会被修改。
因此,当您在排名上运行foreach时,您无法修改其元素,添加新元素或删除任何元素。
答案 1 :(得分:18)
错误告诉您问题是什么(在调试器中运行或读取堆栈跟踪将告诉您问题的确切位置):
C#Collection被修改;枚举操作可能无法执行。
你的问题是循环
foreach (KeyValuePair<int, int> kvp in rankings) {
//
}
其中您修改了集合rankings
。特别是,进攻线是
rankings[kvp.Key] = rankings[kvp.Key] + 4;
在您进入循环之前,请添加以下行:
var listOfRankingsToModify = new List<int>();
用
替换有问题的行listOfRankingsToModify.Add(kvp.Key);
退出循环后
foreach(var key in listOfRankingsToModify) {
rankings[key] = rankings[key] + 4;
}
也就是说,记录您需要进行的更改,并在不重复需要修改的集合的情况下进行更改。
答案 2 :(得分:13)
正如其他人所指出的那样,您正在修改正在迭代的集合,这就是导致错误的原因。违规代码如下:
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
}
.....
上面代码中可能不明显的是Enumerator
来自哪里。在few years back about的一篇博文中,Eric Lippert提供了编译器扩展到foreach
循环的示例。生成的代码如下所示:
{
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();
}
}
如果您查找IEnumerable的MSDN文档(GetEnumerator()
返回的内容),您会看到:
枚举器可用于读取集合中的数据,但不能用于修改基础集合。
这将我们带回错误消息的状态,其他答案重新陈述,您正在修改基础集合。
答案 3 :(得分:5)
我怀疑错误是由此引起的:
foreach (KeyValuePair<int, int> kvp in rankings)
排名是一个字典,它是IEnumerable。通过在foreach循环中使用它,您将指定您希望以延迟方式从字典中获取每个KeyValuePair。也就是说,在循环再次迭代之前,不会返回下一个KeyValuePair。
但是你正在修改循环中的字典:
rankings[kvp.Key] = rankings[kvp.Key] + 4;
这是不允许的...所以你得到了例外。
你可以这么做
foreach (KeyValuePair<int, int> kvp in rankings.ToArray())
答案 4 :(得分:2)
问题出在你执行的地方:
rankings[kvp.Key] = rankings[kvp.Key] + 4;
您无法修改在foreach循环中迭代的集合。 foreach循环要求循环在迭代期间是不可变的。
相反,请使用标准&#39;循环或创建一个新的循环,这是一个副本,并在更新原始文件时迭代它。