在循环中从集合中删除项目(组合框项目)

时间:2013-11-24 15:12:07

标签: .net vb.net visual-studio-2010 combobox foreach

我正在尝试从以"〜$"开头的组合框列表中删除所有项目。

For Each item As String In cstmcmbxDocs.Items
    If Not cstmcmbxDocs.Items.Contains("~$") Then
    Dim STR As Int16 = cstmcmbxDocs.FindString("~$")
    'gets the index of the item which contains "~$"
    cstmcmbxDocs.Items.RemoveAt([STR])
    End If
Next

但它只返回一个删除的实例。 它不会继续搜索 - 我在这里缺少什么? (请注意,我使用的是3.5而不是4+,因为它需要与XP兼容)

1 个答案:

答案 0 :(得分:4)

在使用For Each / Next进行迭代时,无法修改集合(添加或删除)。你也不能使用标准For n As Int32循环。代替:

For n As Int32 = cstmcmbxDocs.Items.Count -1 To 0 Step -1
    ...
    If [your criteria here] Then
        cstmcmbxDocs.Items.RemoveAt(n)   ' remove current one
    End If
Next n

你也应该打开Option Strict:Dim STR As Int16 = cstmcmbxDocs.FindString("~$")不会编译。而且您不需要使用FindString - 您的循环已经开始查看每个项目,因此只需检查每个项目。


为什么For Each循环失败

For Each item As String In cstmcmbxDocs.Items

从这种类型的循环内部删除应该会产生InvalidOperationException。如果您单击获取常规帮助链接,您会发现:

IEnumerator.MoveNext

  

只要集合保持不变,枚举器仍然有效。如果对集合进行了更改,例如添加,修改或删除元素,则枚举数将无法恢复,并且下一次调用MoveNext或Reset会引发InvalidOperationException。


为什么前向For n循环将失败

考虑:

Dim lst As New List(Of String)
lst.AddRange(New String() {"Alpha", "Beta", "Gamma", "Delta", "Echo"})

For n As Int32 = 0 To lst.Count - 1
    If lst(n) = "Gamma" OrElse lst(n) = "Delta" Then
        lst.RemoveAt(n)
    End If
Next

enter image description here

  • 当(n = 2)“Gamma”是当前项目时。
  • 你的代码RemoveAt(n)所以一切都向上移动了。 n现在指向“Delta”
  • 然后Next递增n,现在它指向“Echo”

“Delta”永远不会在循环中进行评估,因为它会被跳过。删除后面的每个元素都将被跳过。这就是MSDN在enumerator is irrecoverably invalidated中的含义。

在这种情况下,你的循环也将耗尽项目!结束循环值lst.Count - 1仅在循环开始时计算。删除项目会减小实际大小,因此最终会导致ArgumentOutOfRangeException崩溃。和以前一样,使用For n循环向后

For n As Int32 = lst.Count - 1 To 0 Step - 1
    If lst(n) = "Gamma" OrElse lst(n) = "Delta" Then
        lst.RemoveAt(n)
    End If
Next

现在,当删除项目时,重新排序的列表部分是代码已经测试的部分。