0

There are a few other questions that touch this subject, but none seem to address it (or then, they are too complex for me to understand them...)

I have a:

Private MCDevices As New Dictionary(Of IPAddress, MCDeviceInfo)

In this Dictionary, the IPAddress are the keys (obviously), and the MCDeviceInfo are Classes defined elsewhere. So it's basically a Dictionnary(Of IPAddress, Class).

I want do a For ... Next loop through the MCDevices Dictionary, and in that loop, I change the contents of the MCDeviceInfo Classes: in the loop, I change the values of the KVP, but no IPAddress is added, changed nor deleted within the loop in any way, and I double-checked that.

For Each kvp As KeyValuePair(Of IPAddress, MCDeviceInfo) In MCDevices
' Some code changing the contents of the MCDeviceInfo but not the IPAddress
Next

Still, reaching the Next, I get:

**System.InvalidIperationException:** 'Collection was modified; enumeration operation may not continue'.

The conditional may here is very optimistic, as the code just stops there...

Is there a way to handle this? Why can't I change the Values as long as the Keys are untouched?

CeSinge
  • 21
  • 6
  • `For ... Next`, not `For Each ... Next` -- Do you have means to relate a `MCDeviceInfo` object to an `IpAddress` Key? Or is it a *blind* change (just change values in `MCDeviceInfo`, no relation with the Key)? – Jimi Dec 19 '20 at 21:13
  • If you want to change the values of a collection, this question may help you: [How to iterate through Dictionary and change values?](https://stackoverflow.com/questions/2260446/how-to-iterate-through-dictionary-and-change-values) - But it is in C# – JayV Dec 19 '20 at 21:30
  • It is a _blind_ change. The `MCDeviceInfo` classes even contain their own IP Address field, so that I'm sure I don't ever have to modify the `Key` of the `KVP`. A `For...Next` may work, but then it looks like I've to convert the `Dictionary` into a `SortedList`, otherwise, I can't seem to find items by IPAddress. – CeSinge Dec 19 '20 at 21:35
  • @JayV : I now gave a harder try at translating the C# of the link you provide into VB, and that seems to work. I'll post my VB code as an answer (tomorrow) - Thank you for that. – CeSinge Dec 19 '20 at 21:58
  • *"in the loop, I change the values of the KVP"*. What does that actually mean? Does it mean that you change property of the object already there or does it mean that you replace that object with a different one. They are two very different things. Maybe show the actual code in the loop that causes the issue. It's always good to show the code that causes the issue if you want the issue fixed. – jmcilhinney Dec 20 '20 at 02:14
  • In the loop, I do not change the Key, so the IP addresses remain untouched, but I do replace the MCDeviceInfo classes, so the Values. – CeSinge Dec 20 '20 at 09:30

2 Answers2

0

You can change the values. Consider the following code and compare it to your secret code:

Imports System.Net

Module Module1

    Private MCDevices As New Dictionary(Of IPAddress, MCDeviceInfo)

    Public Class MCDeviceInfo
        Property Name As String
        Property Vegetarian As Boolean

        Public Overrides Function ToString() As String
            Return $"Name: {Name}"
        End Function
    End Class

    Sub Main()
        MCDevices.Add(IPAddress.Parse("1.1.1.1"), New MCDeviceInfo With {.Name = "Burger", .Vegetarian = False})
        MCDevices.Add(IPAddress.Parse("1.1.1.2"), New MCDeviceInfo With {.Name = "Beanburger", .Vegetarian = True})
        MCDevices.Add(IPAddress.Parse("1.1.1.3"), New MCDeviceInfo With {.Name = "Fries", .Vegetarian = True})

        For Each mcd In MCDevices
            If mcd.Value.Vegetarian Then
                mcd.Value.Name &= " Supersize"
            End If
        Next

        Console.WriteLine(String.Join(vbCrLf, MCDevices))
        Console.ReadLine()

    End Sub

End Module

Outputs:

[1.1.1.1, Name: Burger]
[1.1.1.2, Name: Beanburger Supersize]
[1.1.1.3, Name: Fries Supersize]
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • I trust that this works; meaning then that I do not understand why it doesn't work for me. There is too much code in my case to copy it all here. (note: supersize... a very american example ;-) ) – CeSinge Dec 19 '20 at 21:51
  • @CeSinge I am not American ;) Please reduce your code to the minimal amount to demonstrate the problem and edit the question so that we can reproduce the problem. – Andrew Morton Dec 19 '20 at 21:57
  • The only difference I can see is that I replace the complete `Value Class`, so the complete `MCDeviceInfo` (keeping the key), rather than merely changing _properties of_ that class. – CeSinge Dec 19 '20 at 22:03
  • @CeSinge It looks like you have a solution - the question was "modifying its values", not "replacing its values" ;) – Andrew Morton Dec 19 '20 at 22:07
0

Based on the input of @AndrewMorton, @Jimi and @JayV and @jmcilhinney, I now think that replacing the Values, so replacing the MCDeviceInfo Classes, and not merely changing their properties, is probably the problem.

Also, I now know that the following does not work:

For Each kvp As KeyValuePair(Of IPAddress, MCDeviceInfo) In MCDevices
  ' Some code that changes the properties of the MCDeviceInfo Classes and even
  ' replaces them although the keys, the IPAddresses, are not touched in any way.
Next ' fails on the Next with the error mentioned in my question.

But the following does work (in essence a translation of what @Justin R. wrote in his answer linked to by @JayV in he comments to my initial question):

Dim keys As List(Of IPAddress) = MCDevices.Keys.ToList
For Each key As IPAddress In keys ' Loop over the IPAddress , the keys of the KVP
  ' Some code that changes the properties of the MCDeviceInfo Classes and even
  ' replaces them.
Next

It turns out a For Each is perfectly OK, as much as a regular For...Next is. In the second version, the loop is over a totally separate list, keys.

CeSinge
  • 21
  • 6