Removing an object from an Enumerated Collection

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!
 
S

Stephany Young

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
 
G

Göran Andersson

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.
 
P

Phill W.

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top