从 vb.net 中的列表中删除项目失败
我有一个通用列表,我正在使用 List.Remove(Object)
删除其中的项目。我一直在删除项目,但每当我到达第五个项目时,我删除它都会失败,并且不会将其从列表中删除。我要删除的内容似乎并不重要,但每次我尝试删除五个项目时,第五个项目都会失败。
可能是什么原因造成的?查看 List(Of T).Remove
的文档,它没有指定他们使用什么算法来删除该项目。
I have a generic list that I'm removing items out of using List.Remove(Object)
. I have been removing items but whenever I get to the fifth item I'm removing it fails and does not remove it from the list. It doesn't seem to matter what I'm removing but everytime I try to remove five items it fails on the fifth item.
What could be causing this? Looking at the documentation for List(Of T).Remove
, it doesn't specify what algorithm they're using to remove the item.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Remove
将根据对对象调用.Equals
进行匹配。默认情况下,对于给定对象,它只会匹配相同对象。如果您希望具有相同属性的两个对象被视为相等,即使它们不是同一个对象,您需要重写Equals
方法并将逻辑放在那里。不过,另一个不错的选择是使用
RemoveAll
并传入匿名委托或带有您要查找的条件的 lambda 表达式。例如:当然,只有当您确实想要删除所有匹配项,和/或如果您确定只有一个匹配项时,这才有效。
Remove
is going to match based on calling.Equals
on your objects. By default for a given object it'll only match the same object. If you want two objects with the same properties to be considered equal even if they're not the same object, you need to override theEquals
method and put your logic there.However, another good option is to use
RemoveAll
and pass in an anonymous delegate or a lambda expression with the criteria you're looking for. E.g.:Of course that only works if you really want to remove all the matching items, and/or if you're certain there will only be one that matches.
如果您使用基于索引的方法从列表中删除项目,请记住,当您删除之前的项目时,您删除的项目后面的项目索引将更改 -1。
If you are using an indexed based method to remove items from the list and remember that the indexes of items after the one you remove will change by -1 as you remove the ones before it.
您的清单中有多少项目?你如何删除它们,只是循环?请记住这些是从 0 开始的列表。如果您正在使用整数执行任何类型的 For 循环,则在删除项目时它可能无法工作。
How many items are in your list? How are you removing them, just looping through? Keep in mind these are 0-based lists. If you're doing any sort of For loop with an integer it may not work as you're removing items.
作为一般规则,您不应修改正在循环的集合,而只能修改该集合内的项目。删除 foreach 循环内的项目的问题在于,它会更改正在循环的集合并干扰列表计数和迭代位置。
常见的解决方案是:
向后循环:
这是一个接受
Collection(Of T)
的扩展方法(您可以使用List(Of T)
,但列表类已经公开了RemoveAll
方法基本上做同样的事情)。我们将向后循环并根据传入的 lambda 函数检查集合中每个项目的有效性。如果匹配,我们将删除它。
然后像这样使用:
创建新集合:
使用
RemoveAt
来跟踪集合索引并删除项目会更有效,而不是使用Remove
来获取一个对象,然后检查与该对象匹配的集合的其余部分。但是,如果您确实想要一种方法来处理删除 For 循环中的项目,您可以在原始集合上调用ToList
,从而创建一个新列表。然后,您可以循环新列表以查找需要从原始列表中删除的项目。每当您找到一个对象时,您都可以安全地将其从原始集合中删除,因为它当前尚未被枚举。如需了解更多信息,请查看从“foreach”循环中的列表中删除的答案。
As a general rule, you should not modify a collection that your are looping over, only the items inside of that collection. The problem with removing items inside of a for each loop is that it changes the collection that is being looped and interferes with the list count and iteration location.
Common solutions are to:
Loop Backwards:
Here's an extension method that takes in a
Collection(Of T)
(you could use aList(Of T)
, but the list class already exposes aRemoveAll
method which basically does this same thing).We'll loop backwards and check the validity of each item in the collection based on the passed in lambda function. If it matches, then we'll remove it.
Then use like this:
Create New Collection:
It is more efficient to keep track of the collection index and remove items using
RemoveAt
instead ofRemove
which takes an object and then checks the rest of the collection for matches against that object. However, if you really wanted a way to process removing items within a For Loop, you could callToList
on the original collection, thereby creating a new list. Then, you can loop over the new list to find items that need to be removed from the original. Whenever you find an object, you can safely remove it from the original collection, because it is not currently being enumerated over.For more info, check out this great answer to Remove from a List within a 'foreach' loop.
如果你使用for循环来删除元素,你应该考虑使用foreach,它更适合集合、列表和可数对象
If you are using for loop to remove elements, you should consider using the foreach, it is more suitable for collections, lists and numerable objects