Geeks With Blogs

News test
Chaz Blogs It's all about the eXperience!

Update:

Daniel Moth may have put this a little more concisely on his blog.  I'm not sure I subscribe to his resolution which he admits is a hack.  As he says though, "The real solution is not to remove while iterating; it is bad design."

Instead, iterate through collecting the keys to remove.  Then iterate through your list of keys and remove the associated object from the collection.  This is what I tried to illustrate in my "Good Remove" method below.

Thanks for the e-mail Daniel.  I will look into the posting issue on my blog.

--chaz

 

********************************************************

 

I don't know if the same concept exists in C#, but as of late, I have been running into a lot of trouble with using “RemoveAt” with collections in VB.  If you iterate through a collection in ascending order, you may windup removing an item from the list at an early (0, 1, etc.) index.  This causes all items in the collection to move up one index.  The problem is that your loop doesn't know this happened.  The end result...  you guessed it, index out of range.

Following is a simple piece of code that illustrates the remove loop.  Below it is the collection class. 


Imports System

Namespace JCL_TS.Example.Collections

Public Class Example

Private myCollection As New JCL_TS.Example.Collections.SampleCollection

Public Sub BadRemove()

  For index As Int32 = 0 To MyCollection.Count - 1
    myCollection.RemoveAt(index)
  Next

End Sub

End Class

End Namespace


Imports System
Imports System.Collections

Namespace JCL_TS.Example.Collections

Public Class SampleCollection

   Inherits CollectionBase

   Public Function Item(ByVal index As Int32) As String
      
Return CType(List.Item(index), System.String)
   End
Function

   Public Shadows Sub RemoveAt(ByVal index As Int32)
      
List.RemoveAt(index)
   End Sub

End Class

End Namespace

 

There are many ways around this, like removing a specific key rather than an index.  For example if I change the collection above to have the following method...

Public Sub Remove(ByVal key As String)
       List.Remove(key)
End Sub


Then I would replace the “BadRemove” method in the “Example” with one that first iterates through the collection stashing the matches in an array.  Once I have my matches, I iterate through the array of matches removing the items from the collection accordingly.


Public Sub GoodRemove(ByVal myKey As String)

     Dim keyArray() As String

     Dim counter As Int32 = -1

     For index As Int32 = 0 To myCollection.Count - 1
       
If CType(myCollection.Item(index), System.String) = myKey Then
         
counter += 1
         
ReDim keyArray(counter)
         
keyArray(counter) = myKey
       End If
     Next

     For keyIndex As Int32 = 0 To keyArray.GetUpperBound(0)
        
myCollection.Remove(
CType(keyArray(keyIndex), System.String))
     Next

End Sub


I'm sure that are a number of ways to skin this cat, and I'm sure a number of them are a lot more efficient than my example.  But this works for a quick illustration.  This is the first time I am including a code example in my post.  Let me know if it is helpful or if it needs improvement.

--chaz

Posted on Sunday, August 14, 2005 7:20 PM .Net | Back to top


Comments on this post: RemoveAt

# re: RemoveAt
Requesting Gravatar...
What are you trying to show here? From what I can tell you're replacing badremove() with goodremove(), but the first takes no arguments and the second takes one.

Badremove clears out every item in the collection, good remove clears out all the items in the collections that have a value (not a key) of 'myKey'.

I think you've really hidden the intent of what you're trying to show - try working out a better example peice of code to really show what you're trying to explain.

(This is constructive feedback, and certainly not intended to sound like a flame - it's definately not a flame! :)
Left by Geoff Appleby on Aug 14, 2005 9:37 PM

# re: RemoveAt
Requesting Gravatar...
You're right Geoff. I rushed to throw the example together. I will work it out this week and post a more suitable example.

Thanks for the feedback.
Left by chaz on Aug 15, 2005 8:08 AM

Your comment:
 (will show your gravatar)


Copyright © Chip Lemmon | Powered by: GeeksWithBlogs.net