2011-05-30 82 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

相關問題