Removing an object from an Enumerated Collection

  • Thread starter Thread starter gee-dub
  • Start date Start date
G

gee-dub

Hi,
I need to remove an object from a collection that has been enumerated
with GetEnumerator similar to this...

With lobjs.GetEnumerator
.MoveNext()
if [some_condition] Then
lobjs.remove(.Current)
end if
end with

I realise you can't use the Remove with the GetEnumerator and bombs on
the next MoveNext. is there another way to do this? The API I'm
using requires GetEnumerator (as opposed to For...Each).

Cheers!
 
The question has to be - why?

Is the world going to stop turning if iterate over the collection with For
Each ... Next, or even, for that matter, For ... Next?

I can't imagine any valid reason for the API 'requiring' you to use an
Enumerator.

I can, however, imagine an 'in-house' policy that requires the use of a
Enumerator, but if that is the case then say so, rather than making some
vague statement that doesn't make any sense.

If you remove an item from a collection while you are iterating over it,
then, the rule of thumb is that the collection becomes changed and iterator
is rendered invalid.

This is regardless of whether you are using an Enumerator, a For Each ...
Next iterator or a For ... Next iterator.

If you use a 'backwards' For ... Next iterator then you can remove items
quite happily:

For _i = lobjs.Count - 1 To 0 Step -1
If condition Then lobjs.RemoveAt(_i)
Next

In your case, you could use another collection and do a 2 stage update:

Dim _remove = New List(Of Object)

With lobjs.GetEnumerator
.MoveNext()
If condition Then _remove.Add(.Current)
End With

For Each _obj In _remove
lobjs.Remove(_obj)
Next
 
gee-dub said:
Hi,
I need to remove an object from a collection that has been enumerated
with GetEnumerator similar to this...

With lobjs.GetEnumerator
.MoveNext()
if [some_condition] Then
lobjs.remove(.Current)
end if
end with

I realise you can't use the Remove with the GetEnumerator and bombs on
the next MoveNext. is there another way to do this? The API I'm
using requires GetEnumerator (as opposed to For...Each).

Cheers!

The For Each uses an enumerator, so unless the enumerator is crap, there
is no problem in using a For Each.

As Stephany suggested, to remove the items you just put them in a new
list, and remove them in a separate loop.
 
gee-dub said:
I need to remove an object from a collection that has been enumerated
with GetEnumerator similar to this...

As you've discovered, you can't.
Removing an item invalidates the enumerator on those items.
I realise you can't use the Remove with the GetEnumerator and bombs on
the next MoveNext. is there another way to do this?

Yes. Let the enumerator do its job and, if you want to get rid of an
item, add it to another list so that you can purge them out once you the
"the end", something like:

e = data.GetEnumerator()

Do While e.MoveNext()
if NeedToDelete( e.Current ) then
trash.add( e.Current )
end if
Loop

' Remove the ones we've marked for deletion
' (backwards, of course)
For i As Integer = data.Count - 1 To 0 Step -1
If trash.Contains( data( i ) ) then
data.RemoveAt( i )
End If
Next
The API I'm using requires GetEnumerator
(as opposed to For...Each).

Never come across anything like that before.
Which one is it?

Regards,
Phill W.
 
Back
Top