2011-05-30 152 views
26

Possible Duplicate:
Collection was modified; enumeration operation may not executeC#集合已被修改;枚举操作可能不会执行

您好,

我建立一个项目评估程序,并正在以下错误:C#集合已修改;枚举操作可能不会执行。我initally这个全球声明diciontary :

它关系到使用该

Dictionary<int, int> rankings = new Dictionary<int, int>(); 

含本词典下一个方法执行以下操作:

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

btw,脱离主题,你的MySqlConnection和MySqlDataReader类不会实现IDisposable到Dispose()方法,这样你就可以使用block来连接和阅读器了吗? – 2011-05-30 14:49:40

+1

@ydobonmai:'MySqlConnection'和'MySqlDataReader'可能是指用于处理MySQL数据库的'MySql.Data.MySqlClient'类。因此,他们确实实现了'IDisposable',并且他们的使用应该被封装在'使用'块中。 – jason 2011-05-30 15:04:34

回答

80

,你遍历用foreach任何收集任何帮助可能无法迭代过程中被修改。

所以,当你运行排名foreach,你不能修改它的元素,添加新的或删除任何。

+22

然而,您可以循环收集该集合的副本。例如循环实例中的'Collection.ToArray()'。这样可以让您在循环中修改实际的集合,同时不会更改集合的“副本”。来源http://stackoverflow.com/questions/604831/collection-was-modified-enumeration-operation-may-not-execute – 2014-03-12 15:35:37

+3

+1 Don:ToArray()修复它。 +1到@Roy也是如此。 – Mukus 2014-03-28 03:59:39

+0

我想知道为什么这个bug还没有修复。 – 2014-06-22 20:26:40

18

错误告诉你到底是什么问题(并在调试运行或读取堆栈跟踪会告诉你到底哪里出了问题):

C# Collection was modified; enumeration operation may not execute.

你的问题是循环

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; 
} 

即,记录您需要做出的更改,并使其无需迭代需要修改的集合。

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()) 
2

问题出在哪里,你都在执行:

rankings[kvp.Key] = rankings[kvp.Key] + 4; 

您不能修改您在foreach循环迭代通过集合。 foreach循环要求循环在迭代期间是不可变的。

相反,使用标准的'for'循环或创建一个新的循环,它是一个副本,并在更新原始文件时迭代。

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()收益),你会看到:

Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.

这把我们带回到了错误什么消息状态和其他答案重新显示,您正在修改基础集合。

+0

潜在读者:请忽略downvote,它是在一个nerdrage适合。罗马:如果你编辑这个答案,我会删除downvote,它过去的时间限制,不会让我这样做。 – heisenberg 2011-06-22 21:29:24

相关问题