Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify a dictionary which I am iterating through

Tags:

c#

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

An exception was thrown:

Collection was modified; enumeration operation may not execute.

For some reason, it is not any more.

I know you cannot remove something, while iterating through it this way. My question is: How do I solve it?

like image 313
Basser Avatar asked Aug 17 '10 19:08

Basser


People also ask

Can you modify a dictionary while iterating?

To modify a Python dict while iterating over it, we can use the items method to get the key and value. to loop through the key value pairs in t with t. items() and the for loop. In it, we set t2[k] to the prefix + v where v is the value in the t dict.

Can you modify a dictionary?

Yes you can, dictionary is an mutable object so they can be modified within functions, but it must be defined before you actually call the function.

How do you modify a list while iterating?

The general rule of thumb is that you don't modify a collection/array/list while iterating over it. Use a secondary list to store the items you want to act upon and execute that logic in a loop after your initial loop. Show activity on this post. And it should do it without any errors or funny behaviour.


2 Answers

You can't modify a collection you're iterating over. In this case, a much better solution would be to create a list of entries to remove by iterating over the dictionary, and then iterate over that list, removing the entries from the dictionary:

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

Note that if you're using .NET 3.5, you could use a LINQ query to express the first part:

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(); 
like image 156
Jon Skeet Avatar answered Sep 22 '22 14:09

Jon Skeet


Simply put: you can't remove an entry from a collection while you are iterating over it.

One possible workaround is to create a shallow copy of the collection (e.g using ToList) and iterate over that :

foreach(BruteforceEntry be in Entries.Values.ToList()) {     // modify the original collection } 
like image 21
digEmAll Avatar answered Sep 19 '22 14:09

digEmAll