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

Измените словарь, который я повторяю через

foreach(BruteforceEntry be in Entries.Values)
{
    if (be.AddedTimeRemove <= now)
        Entries.Remove(be.IPAddress);
    else if (be.Unbantime <= now && be.Unbantime.Day == DateTime.Now.Day)
        Entries.Remove(be.IPAddress);
}

Исправлено исключение:

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

По какой-то причине это уже не так.

Я знаю, что вы не можете удалить что-то, итерации через него таким образом. Мой вопрос: как его решить?

4b9b3361

Ответ 1

Вы не можете изменить коллекцию, которую вы перебираете. В этом случае гораздо лучшим решением было бы создать список записей для удаления с помощью итерации по словарю, а затем перебрать этот список, удалив записи из словаря:

List<string> removals = new List<string>();                    
DateTime now = DateTime.Now;
foreach(BruteforceEntry be in Entries.Values)
{
    if (be.AddedTimeRemove <= now ||
        (be.Unbantime <= now && be.Unbantime.Day == DateTime.Now.Day))
    {
        removals.Add(be.IPAddress);
    }
}
foreach (string address in removals)
{
    Entries.Remove(address);
}

Обратите внимание, что если вы используете .NET 3.5, вы можете использовать запрос LINQ для выражения первой части:

List<string> removals = (from be in Entries.Values
                         where be.AddedTimeRemove <= now ||
                               (be.Unbantime <= now && 
                                be.Unbantime.Day == DateTime.Now.Day)
                         select be.IPAddress).ToList();

Ответ 2

Проще говоря: вы не можете удалить запись из коллекции во время ее итерации по ней.

Возможным обходным путем является создание мелкой копии коллекции (например, с помощью ToList) и повторение этого:

foreach(BruteforceEntry be in Entries.Values.ToList())
{
    // modify the original collection
}

Ответ 3

Вы можете изменить foreach(BruteforceEntry be in Entries.Values) на foreach(BruteforceEntry be in new List<BruteforceEntry>(Entries.Values))

Таким образом, вы не изменяете свою коллекцию, а скорее ее копию.

Ответ 4

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

Ответ 5

Вы не можете изменять коллекцию при повторении с помощью foreach. Вместо этого проведите по ней цикл for.

Ответ 6

Это (на мой взгляд) самый простой способ:

Dictionary<String, String> A = new Dictionary<string, string>(); //Example Dictionary
A.Add("A", "A"); //Example Values
A.Add("B", "B");
A.Add("C", "C");

for (int i = A.Count - 1; i >= 0; i--) //Loop backwards so you can remove elements.
{
     KeyValuePair<String, String> KeyValue = A.ElementAt(i); //Get current Element.
     if (KeyValue.Value == "B") A.Remove(KeyValue.Key);
}

В вашем случае:

for (int i = Entries.Count - 1; i >= 0; i--)
{
    KeyValuePair<String, BruteforceEntry> KeyValue = Entries.ElementAt(i);
    if (KeyValue.Value.AddedTimeRemove <= now)
         Entries.Remove(KeyValue.Key);
    else if (KeyValue.Value.Unbantime <= now && KeyValue.Value.Unbantime.Day == DateTime.Now.Day)
         Entries.Remove(KeyValue.Key);
}

Ответ 7

Устранив вашу проблему...

foreach(... ... in Entries.Values)
{
        Entries.Remove(...);

}

Как говорили другие, вы изменяете итератор во время итерации.

Вы можете, как сказал @David, использовать цикл for, но обязательно начинайте с конца (обратная итерация).