Changing a Collection from within a loop
I have a simple Dictionary(of String, Object)
that I need to iterate through and change items depending on some conditions.
As I can't modify a collection that I'm iterating through, how do I achieve this?
For example, the following obviously causes an Invalid Operatio开发者_如何学编程n Exception
:
Dim mOptions As New Dictionary(of String, Object)
mOptions.Add("optA", "A")
mOptions.Add("optB", "B")
mOptions.Add("optC", "C")
For Each O As KeyValuePair(Of String, Object) In mOptions
Dim Val As Object = GetSomeOtherObjectBasedOnTheOption(O.Key, O.Value)
mOptions(O.Key) = Val
Next
Invalid Operation Exception
Collection was modified; enumeration operation may not execute.I guess I need to Clone the Dictionary first and iterate over the copy? What's the best way of doing that?
Dim TempOptions As New Dictionary(of String, Object)
For Each O As KeyValuePair(Of String, Object) In mOptions
TempOptions.Add(O.Key, O.Value)
Next
For Each O As KeyValuePair(Of String, Object) In TempOptions
Dim Val As Object = GetSomeOtherObjectBasedOnTheOption(O.Key, O.Value)
mOptions(O.Key) = Val
Next
That smells a bit though.
You can just iterate over a copy of the keys instead of iterating over the KeyValuePair
s.
For Each K as String in mOptions.Keys.ToArray()
Dim Val As Object = GetSomeOtherObjectBasedOnTheOption(K)
mOptions(K) = Val
Next
(sorry if you can't just paste that in -- I don't normally write VB)
It doesn't strictly have to be an array: you can do the VB equivalent of foreach (string k in new List<string>(mOptions.Keys))
as well, for instance.
If you iterate over the original keys and modify your dictionary, you'll get the same error.
Why iterate over KeyValuePairs?
Why not do this?
For Each K As String In mOptions.Keys.ToArray()
Dim Val As Object = GetSomeOtherObjectBasedOnTheOption(K)
mOptions(K) = Val
Next
This way, the collection your iterating over is a list of strings which can be used to access the Dictionary, not the Dictionary itself.
Apologies in advance for any crap VB. Haven't done it in years
in C# this can be done by using the yield pattern, don't know if it's also possible in VB.NET, otherwise you could create a custom IEnumerable that allows it...
精彩评论