VB6 and VB.NET collections differ in a substantial way: you can’t modify a VB.NET collection (or any .NET collection, for that matter) from inside a For Each loop that is iterating over the collection itself. You see the problem in the following piece of code, which is quite common in VB6:
Dim frm As Form
For Each frm In Forms
Unload frm
Next
The code is translated almost literally to .NET:
Dim frm As VB6Form
For Each frm In Forms6
Unload6(frm)
Next
foreach (VB6Form frm in VBProject.Forms)
{
VB6Helpers.Unload(frm);
}
When you run the above code, the Next statement throws an InvalidOperationException error whose message is quite self-explanatory:
Collection was modified; enumeration operation may not execute.
VB Migration Partner doesn’t fix this issue automatically. However, you can edit the original VB6 code to use the CloneCollection6 method defined in VBMigrationPartner_Support.bas module:
Dim frm As Form
For Each frm In CloneCollection6(Forms)
Unload frm
Next
When converting to C#, you have slightly modify the code so that it uses the method defined in the VB6Helpers class:
foreach (VB6Form frm in VB6Helpers.CloneCollection(VBProject.Forms))
{
VB6Helpers.Unload(frm);
}
The VB6 version of the CloneCollection6 method simply returns its argument, therefore the original program isn’t affected in any way. The .NET version of the method (defined in the support library) creates and returns a copy of the original collection, therefore the loop iterates on a collection instance other than the instance being modified in the loop itself and no runtime error occurs.
In a few special cases you might prefer not to create a clone of the original collection, for example if the collection has too many elements and the copy operation would add a noticeable overhead. In such special cases, you can avoid the issue by replacing the For Each block with a regular For loop, as in:
Dim i As Integer
For i = Forms.Count – 1 To 0 Step -1
Unload Forms(i)
Next
or
Dim i As Integer
For i = 1 To Forms.Count
Unload Forms(0)
Next