11

I use the following code to remove all elements from a dictionary:

internal static void RemoveAllSourceFiles()
        {
            foreach (byte key in taggings.Keys)
            {
                taggings.Remove(key);
            }
        }

But unfortunately this isn't working because an InvalidOperationException is thrown. I know this is because the collection is modified while iterating over it, but how can I change that?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 1
    Note: While in this specific case `Clear` makes much more sense, in the general case you can solve this problem by iterating over a copy of the list of keys, e.g. by using `foreach (byte key in taggings.Keys.ToList())`. – Brian Mar 09 '11 at 14:51
  • Thanks, this helped me. The `Clear` approach does not work in my case, because I need some events to be triggered on removal of the items. – waldgeist Apr 20 '19 at 20:49

6 Answers6

37

A much simpler (and much more efficient) approach:

taggings.Clear();

and yes, the error is because changing the data deliberately breaks iterators.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
6

Try using the Clear method instead.

internal static void RemoveAllSourceFiles()
        {
           taggings.Clear();
        }

Update: And as Marc pointed out, you cannot continue iterating over a collection while you modify it because the iterator is irrecoverably invalidated. Please read the answer to this SO question for details.

Why does enumerating through a collection throw an exception but looping through its items does not

Community
  • 1
  • 1
Unmesh Kondolikar
  • 9,256
  • 4
  • 38
  • 51
4

Dictionary.Clear?

Cameron MacFarland
  • 70,676
  • 20
  • 104
  • 133
2

To do what you want to do you are going to need to iterate through the keys in reverse, that way you do not modify the array in the order it is trying to return to you.

Either that or use .Clear()

Dested
  • 6,294
  • 12
  • 51
  • 73
2

As said, the .NET default enumerator doesn't support collection changes while enumerating. In your case use Clear.

If you want better control over deletion, use linq:

var deletionList = (from tag in taggings where <where clause> select tag.Key).ToArray();
foreach(var key in deletionList)
{
   taggings.Remove(key);
}

The ToArray() extension method will enumerate the LINQ query, and instantiate an array storing the results. This array can be safely enumerated later to delete the contained items in the source dictionary.

Eilistraee
  • 8,220
  • 1
  • 27
  • 30
0

I know this is an old question, but for any who's looking for an answer, here some options:

  • To list() and then use the .remove property.
  • Make it null/nothing and reinit it?
  • Forloop in stead of foreach?
while Dict.Count()
  clDictObject oBj = Dict.Keys.ElementAt(dict.Count -1);
  Dict.Remove(oBj)
end while
double-beep
  • 5,031
  • 17
  • 33
  • 41