initialize generate c# collections dictionary

generate - Se modificó la colección C#; operación de enumeración no puede ejecutar



initialize dictionary c# (5)

Posible duplicado:
La colección fue modificada; operación de enumeración no puede ejecutar

Hola,

Estoy creando un programa de estimación de proyectos y obtengo el siguiente error: se modificó C # Collection; La operación de enumeración no puede ejecutarse.

Está relacionado con el uso de esto: inicialmente declaro el diciontario globalmente con esto:

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

El siguiente método que contiene este diccionario hace lo siguiente:

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

Lo llamo por segunda vez aquí:

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

El problema surge en esta área del código:

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

Cualquier ayuda con donde se encuentre el problema será muy apreciada.


Como han señalado otros, está modificando una colección sobre la que está iterando y eso es lo que está causando el error. El código ofensivo está abajo:

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

Lo que puede no ser obvio del código anterior es de dónde proviene el Enumerator . En una publicación de un blog de hace unos años sobre Eric Lippert, se proporciona un ejemplo de cómo el compilador amplía un bucle foreach . El código generado se verá algo así como:

{ 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(); } }

Si busca la documentación de MSDN para IEnumerable (que es lo que devuelve GetEnumerator() ) verá:

Los enumeradores pueden usarse para leer los datos en la colección, pero no pueden usarse para modificar la colección subyacente.

Lo que nos devuelve a lo que indica el mensaje de error y las otras respuestas se vuelven a establecer, está modificando la colección subyacente.


Cualquier colección que se repita con foreach no se puede modificar durante la iteración.

Entonces, mientras ejecuta un Foreach sobre clasificaciones, no puede modificar sus elementos, agregar nuevos o eliminar ninguno.


El error le dice EXACTAMENTE cuál es el problema (y ejecutar en el depurador o leer el seguimiento de la pila le dirá exactamente dónde está el problema):

Se modificó la colección C #; La operación de enumeración no puede ejecutarse.

Tu problema es el bucle.

foreach (KeyValuePair<int, int> kvp in rankings) { // }

en el que modificas los rankings colección En particular, la línea ofensiva es

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

Antes de ingresar al bucle, agregue la siguiente línea:

var listOfRankingsToModify = new List<int>();

Reemplace la línea ofensiva con

listOfRankingsToModify.Add(kvp.Key);

y después de salir del bucle

foreach(var key in listOfRankingsToModify) { rankings[key] = rankings[key] + 4; }

Es decir, registre los cambios que necesita hacer y hágalos sin iterar sobre la colección que necesita modificar.


El problema es donde estas ejecutando:

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

No puede modificar la colección que está iterando en un bucle foreach. Un bucle foreach requiere que el bucle sea inmutable durante la iteración.

En su lugar, use un bucle ''for'' estándar o cree un nuevo bucle que sea una copia y repítalo mientras actualiza su original.


Sospecho que el error es causado por esto:

foreach (KeyValuePair<int, int> kvp in rankings)

Las clasificaciones son un diccionario, que es IEnumerable. Al usarlo en un bucle foreach, está especificando que desea que cada KeyValuePair del diccionario sea diferido. Es decir, el próximo KeyValuePair no se devuelve hasta que el bucle se repita nuevamente.

Pero estás modificando el diccionario dentro de tu bucle:

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

lo que no está permitido ... así que obtienes la excepción.

Simplemente podrías hacer esto

foreach (KeyValuePair<int, int> kvp in rankings.ToArray())