本文介绍了在循环中从集合中删除项目(组合框项目)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

对于 cstmcmbxDocs.Items 中的每个项目作为字符串如果不是 cstmcmbxDocs.Items.Contains("~$") 然后Dim STR As Int16 = cstmcmbxDocs.FindString("~$")'获取包含~$"的项目的索引cstmcmbxDocs.Items.RemoveAt([STR])万一下一个

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

解决方案

在使用 For Each/Next 进行迭代时,您不能修改(添加或删除)集合.您也不能使用标准的 For n As Int32 循环.相反:

For n As Int32 = cstmcmbxDocs.Items.Count -1 To 0 Step -1...如果 [您的标准] 那么cstmcmbxDocs.Items.RemoveAt(n) ' 删除当前的万一下一个

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


为什么 For Each 循环失败

对于每个项目作为字符串在 cstmcmbxDocs.Items

从这种类型的循环内部删除应该会导致 InvalidOperationException.如果您点击获取一般帮助链接,您会发现:

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

三角洲"永远不会在循环中评估,因为它被跳过.删除后的每个元素都将被跳过.这就是 MSDN 所说的枚举器不可恢复地失效.

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

向后循环

For n As Int32 = lst.Count - 1 To 0 Step - 1如果 lst(n) = Gamma"OrElse lst(n) = Delta"然后lst.RemoveAt(n)万一下一个

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

I am trying to remove all items from a combo box list that begin with "~$".

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

But it only returns one instance which it removes.It doesn't continue searching - what am i missing here?(Note that I am using 3.5 and not 4+ because it needs to be compatible with XP)

解决方案

You cannot modify a collection (add or delete) as you iterate using For Each/Next. Nor can you use a standard For n As Int32 loop. Instead:

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

You should also turn on Option Strict: Dim STR As Int16 = cstmcmbxDocs.FindString("~$") wont compile. And you do not need to use FindString - your loop is already going to look at each item, so just examine each for the condition.


Why a For Each loop fails

For Each item As String In cstmcmbxDocs.Items

Removing from inside this type of loop should result in an InvalidOperationException. If you click the Get general help link you find this:

IEnumerator.MoveNext


Why a forward For n loop will fail

Consider:

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
  • When (n=2) "Gamma" is the current item.
  • Your code RemoveAt(n) so everything moves up one. n now points to "Delta"
  • Then Next increments n so it now points to "Echo"

"Delta" is never evaluated in the loop because it is skipped. Every element after a deleted one will be skipped. This is what MSDN means by enumerator is irrecoverably invalidated.

In this case, your loop will also run out of items! The end loop value, lst.Count - 1 is calculated only at the start of the loop. Removing items reduces the actual size so it will eventually crash with an ArgumentOutOfRangeException. As before, loop backwards using 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

Now, when items are removed, the part of the list which is reordered is the part the code has already tested.

这篇关于在循环中从集合中删除项目(组合框项目)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 03:16
查看更多