5

我有一个通用列表,我正在删除正在使用的项目List.Remove(Object)。我一直在删除项目,但每当我到达第五个项目时,我将其删除失败并且不会将其从列表中删除。我要删除的内容似乎并不重要,但每次我尝试删除五个项目时,它都会在第五个项目上失败。

这可能是什么原因造成的?查看 的文档List(Of T).Remove,它没有指定他们使用什么算法来删除该项目。

4

5 回答 5

12

Remove将根据调用.Equals您的对象进行匹配。默认情况下,对于给定的对象,它只会匹配同一个对象。如果您希望两个具有相同属性的对象即使不是同一个对象也被视为相等,您需要重写该Equals方法并将您的逻辑放在那里。

但是,另一个不错的选择是使用RemoveAll并传入匿名委托或带有您正在寻找的条件的 lambda 表达式。例如:

customers.RemoveAll(customer => customer.LastName.Equals(myCustomer.LastName));

当然,只有当你真的想删除所有匹配的项目时,这才有效,和/或如果你确定只有一个匹配的项目。

于 2009-12-17T18:42:57.647 回答
2

如果您使用基于索引的方法从列表中删除项目,请记住,您删除的项目的索引将在您删除之前的项目时更改 -1。

于 2009-12-17T16:42:08.520 回答
0

您的清单中有多少项目?您如何删除它们,只是循环播放?请记住,这些是基于 0 的列表。如果您使用整数执行任何类型的 For 循环,则在删除项目时它可能无法正常工作。

于 2009-12-17T16:39:12.513 回答
0

作为一般规则,您不应该修改您正在循环的集合,只修改该集合中的项目。删除 for each 循环中的项目的问题在于它会更改正在循环的集合并干扰列表计数和迭代位置。

常见的解决方案是:

  1. 向后循环遍历集合,因此对迭代器的干扰不会影响执行
  2. 创建一个新集合,以便您可以修改一个集合并循环另一个集合。

向后循环:

这是一个接受 a 的扩展方法Collection(Of T)(您可以使用 a List(Of T),但列表类已经公开了一个RemoveAll基本上做同样事情的方法)。
我们将向后循环并根据传入的 lambda 函数检查集合中每个项目的有效性。如果匹配,我们将删除它。

<Extension()>
Public Sub RemoveEach(Of T)(ByRef col As Collection(Of T),
                            ByVal match As Func(Of T, Boolean))
    For i = col.Count - 1 To 0 Step -1
        If match(col(i)) Then col.RemoveAt(i)
    Next
End Sub

然后像这样使用:

Dim col = New Collection(Of Integer)({1, 2, 3, 4}.ToList)
col.RemoveEach(Function(i) (i Mod 2) = 0)
'Produces list of 1 & 3

创建新集合:

跟踪集合索引并删除项目更有效,RemoveAt而不是使用Remove对象,然后检查集合的其余部分是否与该对象匹配。但是,如果您真的想要一种方法来处理在 For 循环中删除项目,您可以调用ToList原始集合,从而创建一个新列表。然后,您可以遍历新列表以查找需要从原始列表中删除的项目。每当您找到一个对象时,您都可以安全地从原始集合中删除它,因为它当前没有被枚举。

<Extension()>
Public Sub RemoveEachObject(Of T)(ByRef col As Collection(Of T), 
                                  ByVal match As Func(Of T, Boolean))
    For Each o As T In col.ToList()
        If match(o) Then col.Remove(o)
    Next
End Sub

有关更多信息,请查看在“foreach”循环中从列表中删除的出色答案。

于 2014-03-03T15:40:45.547 回答
-1

如果你使用for循环删除元素,你应该考虑使用foreach,它更适合于集合、列表和可数对象

于 2009-12-17T16:42:03.990 回答