Find the index of a particular object when foreaching on a custom collection derived from CollectionBase – level 200

I labeled this post as 200 instead of 100 because I imagine that beginners in .Net won’t be creating their own custom collection classes.  I think once someone can create their own custom collections, they should be considered at least intermediate.


Today a colleague approached me with a problem.  He was foreaching through a custom collection in C#, and when he evaluated the object he wanted, he need the index of that object for the collection.  He was approaching the problem with calls to GetEnumerator(), etc, and I shared with him what I do for this situation:



  • When you inherit from CollectionBase, your collection data structure is an ArrayList.  if you look at the InnerList protected member, it is of type ArrayList.  The ArrayList type has a method IndexOf(object) that returns int, the index of the object within the ArrayList.

  • To make the index available to callers of your custom collection, define a method like so:

        public int IndexOf(object value)

{

return base.InnerList.IndexOf(value);

}


  • So now, when you have an object you can pass it to this method to get the index of that object within the instance of your collection.

When I create my own collection types, I normally expose all the helper methods of the InnerList so that my collection is as functional as possible.  Inheriting from CollectionBase just strongly types the ArrayList object for you.  With generics in v2.0, if you don’t need any extra functionality from your collections, then you’ll just want to go with ArrayList<T> or you can use the new Collection<T> class:

    public class Junk<T> : Collection<T>

{

private int m_myExtraMember;

public Junk(int myExtraMember)

{

m_myExtraMember = myExtraMember;

}

public new int IndexOf(T value)

{

return base.IndexOf(value);

}

}

With v2.0 and generics, you may still want to implement your own custom collections if you need to track a member that isn’t included, but still, this method is simplified.  I have overriden the IndexOf() method unnecessarily just to show some syntax.  With 2.0, all you would need is the m_myExtraMember field.  IndexOf is inherited.


Another tip about collections:  Know what data structure the collection uses internally.  Collection<T> uses the List<T> structure internally which is similar to ArrayList in that it keeps the objects in the same order in which they were inserted.  With HashTable-based collections, the objects are retrieved via key, and the order is not guaranteed, so if  you foreach on a HashTable, you can never know in what order the objects will be retrieved.  I hope this post helps someone.