问题描述
我正在尝试从组合框列表中删除以~$"开头的所有项目.
对于 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:
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
incrementsn
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.
这篇关于在循环中从集合中删除项目(组合框项目)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!