Ended up with the following for my ICollection interface:

namespace Testing.Collections

{

    public interface ICollection<A>

    {

        /// <summary>

        /// Attempts to add an element into this collection

        /// </summary>

        /// <param name="element">The element to add into this collection</param>

        /// <returns>true if the element was successfully added, false otherwise</returns>

        bool Add(A element);

 

        /// <summary>

        /// Returns true if this collection is Empty, false otherwise.

        /// </summary>

        /// <value></value>

        bool Empty

        {

            get;

        }

 

        /// <summary>

        /// Removes all the elements contained in this collection.

        /// </summary>

        /// <exception>A NotSupportedException is thrown if the collection cannot be cleared</exception>

        void Clear();

 

        /// <summary>

        /// Determines whether an element is in this collection

        /// </summary>

        /// <param name="element">The element to locate in this collection</param>

        /// <returns>Returns true if the element is contained within this collection. 

        /// determining containment is left up to the concrete implementation

        /// to define.</returns>

        bool Contains(A element);

 

        /// <summary>

        /// Removed the first occurance of the specified element from this collection

        /// </summary>

        /// <param name="element">The element to remove</param>

        /// <returns>Returns true if the element is contained within this collection and

        /// subsequently removed.  Determining containment is left up to the concrete

        /// implementation to define.</returns>

        bool Remove(A element);

    }

}

The next issue on the plate is how to get to the elements in the collection.  I stated earlier that i don't necessarily want to limit myself to finite collections, so indexing into the collection seems out.  The only other option i see it some way to query collection for all of it's elements one at a time.  i.e. implementing the Iterator pattern (see Design Patterns).  However, there are several choices you can make (with corresponding tradeoffs).  The first thing I need to decide on is if these collections are going to support internal or external iteration (or both).  External iteration is done with the pattern we commonly see in the BCL.  I.e.

IEnumerator<A> GetEnumerator();

Calling GetEnumerator returns an IEnumerator that one can foreach across to access all elements.  Alternatively we can use internal iteration which looks like:

void Iterate(Predicate<A> p);

When you call this you pass a delegate that will be performed on each element in the list.  The delegates return value says if we should continue.  Returning true is equivalent to “continue”ing in a foreach, returning false is equivalent to “break”ing out of a foreach.  I might also provide:

void Iterate(Operator<A> p);

Which will iterate over every element without stopping.  An example of using both is shown here:

            foreach (int i in collection)

            {

                Console.WriteLine(i);

            }

 

            collection.Iterate(delegate(int i) {

                Console.WriteLine(i);

            });

Or, we could have something like:

            foreach (int i in collection)

            {

                Console.WriteLine(i);

                if (i > 10)

                {

                    break;

                }

            }

 

            collection.Iterate(delegate(int i) {

                Console.WriteLine(i);

                return i <= 10;

            });

I'm not sure which i prefer, although I am strongly leaning toward Iterate.  It allows for far easier implementation of the Iterator (try implementing GetEnumerator on a tree versus Iterate on a tree).  However, you are more limited in what you can do.  For example, if sublasses return specialized IEnumerators (like IListEnumerator or ITreeEnumerator) then this can't really be expressed well in the Iterate model.  Also, because you are iterating all at once, it makes it difficult to weave enumerators together.  (try writing ArrayCollection.Equals with just Iterate versus ArrayCollection.Equals using GetEnumerator).