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.

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:

  1. Loop through the collection backwards so interferences with the iterator won't impact the execution
  2. Create a new collection so you can modify one collection and loop over another.

###Loop Backwards:

Here's an extension method that takes in a Collection(Of T) (you could use a List(Of T), but the list class already exposes a RemoveAll 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.

<!-- language: lang-vb -->
<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

Then use like this:

<!-- language: lang-vb -->
Dim col = New Collection(Of Integer)({1, 2, 3, 4}.ToList)
col.RemoveEach(Function(i) (i Mod 2) = 0)
'Produces list of 1 & 3

###Create New Collection:

It is more efficient to keep track of the collection index and remove items using RemoveAt instead of Remove 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 call ToList 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.

<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

For more info, check out this great answer to Remove from a List<T> within a 'foreach' loop.