Подтвердить что ты не робот

Коллекция С# была изменена; операция перечисления может не выполняться

Возможный дубликат:
Изменена коллекция; операция перечисления не может выполняться

HI,

Я создаю программу оценки проекта и получаю следующую ошибку: С# Collection был изменен; операция перечисления не может выполняться.

Это связано с использованием этого: Я сначала объявляю 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();
    }
}

Любая помощь в том, где лежит проблема, будет высоко оценена

4b9b3361

Ответ 1

Любая коллекция, которую вы перебираете с помощью foreach, не может быть изменена во время итерации.

Итак, пока вы используете foreach над рейтингами, вы не можете изменять его элементы, добавлять новые или удалять любые.

Ответ 2

Ошибка сообщает вам ТОЧНО, в чем проблема (и работа в отладчике или чтение трассировки стека расскажет вам, где именно проблема):

Коллекция С# была изменена; операция перечисления не может выполняться.

Ваша проблема в цикле

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

То есть, запишите, какие изменения нужно внести, и сделайте их без повторения коллекции, которую вам нужно изменить.

Ответ 3

Как указывали другие, вы изменяете коллекцию, которую вы повторяете, и то, что вызывает ошибку. Код нарушения ниже:

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. В сообщении в блоге из несколько лет назад Эрик Липперт дает пример того, что цикл 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();
    }
}

Если вы посмотрите документацию MSDN для IEnumerable (что возвращает GetEnumerator()), вы увидите:

Перечислители могут использоваться для чтения данных в коллекции , но они не могут использоваться для изменения базовой коллекции.

Что возвращает нас к состоянию сообщения об ошибке, а другие ответы переустанавливают, вы изменяете базовую коллекцию.

Ответ 4

Я подозреваю, что ошибка вызвана этим:

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

Ответ 5

Проблема заключается в том, где вы выполняете:

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

Вы не можете изменять коллекцию, которую вы выполняете в цикле foreach. Цикл foreach требует, чтобы цикл был неизменным во время итерации.

Вместо этого используйте стандартный цикл 'for' или создайте новый цикл, который является копией и повторите это при обновлении оригинала.