Collection Interfaces and c sharp

Every collection has certain shared characteristics, which are captured by the collection interfaces. The .NET Framework provides standard interfaces for enumerating, comparing, and creating collections.


By implementing the collection interfaces, your custom class provides the same semantics as the collection classes available through the .NET Framework.

IEnumerable

Enumerates through a collection using a foreach statement

IEnumerator

Iterates over a collection and supports the foreach loop

ICollection

Implemented by all collections

IComparer

Compares two objects; used for sorting

IList

Used by collections that can be indexed

IDictionary

For key/value-based collections such as Hashtable and SortedList

IDictionaryEnumerator

Allows enumeration with foreach of a collection that supports IDictionary

Now focus on the IEnumerable interface, using it to demonstrate how you can implement the collection interfaces in your own classes to allow clients to treat your custom classes as if they were collections. For example, you might create a custom class named ListBoxTest. Your ListBoxTest will have a set of strings to be displayed. You can implement the collection interfaces in your ListBoxTest class to allow clients to treat your ListBoxTest as if it were a collection. This allows clients to add to the ListBoxTest using the index operator (e.g., myListBox[5] = "New String"), to sort the ListBoxTest, to enumerate the elements of the ListBoxTest, and so forth.

The IEnumerable Interface

IThe foreach statement will work with any class that implements the IEnumerable interface. Classes that implement the IEnumerable interface have a single method, GetEnumerator(), that returns an object that implements a second interface, IEnumerator.

The entire job of the IEnumerable interface is to define the GetEnumerator() method. The job of the GetEnumerator() method is to generate an enumerator — that is, an instance of a class that implements the IEnumerator interface.

By implementing the IEnumerable interface, your ListBoxTest class is saying "you can enumerate my members, just ask me for my enumerator." The client asks the ListBoxTest for its enumerator by calling the GetEnumerator() method. What it gets back is an instance of a class that knows how to iterate over a list box. That class, ListBoxEnumerator, will implement the IEnumerator interface.

This gets a bit confusing, so let's use an example. When you implement the IEnumerable interface for ListBoxTest, you are promising potential clients that ListBoxTest will support enumeration. That allows clients of your ListBoxTest class to write code like this:

foreach (string s in ListBoxTest) { //... }

You implement IEnumerable by providing the GetEnumerator() method, which returns an implementation of IEnumerator. In this case, you'll return an instance of ListBoxEnumerator, and ListBoxEnumerator will implement the IEnumerator interface:

 public IEnumerator GetEnumerator()

{

return (IEnumerator) new ListBoxEnumerator(this);

The ListBoxEnumerator is a specialized instance of IEnumerator that knows how to enumerate the contents of your ListBoxTest class. Notice two things about this implementation. First, the constructor for ListBoxEnumerator takes a single argument, and you pass in the this reference. Doing so passes in a reference to the current ListBoxTest object, which is the object that will be enumerated. Second, notice that the ListBoxEnumerator is cast to an IEnumerator before it is returned. This cast is safe because the ListBoxEnumerator class implements the IEnumerator interface.


An alternative to creating a specialized class to implement IEnumerator is to have the enumerable class (ListBoxTest) implement IEnumerator itself. In that case, the IEnumerator returned by GetEnumerator would be the ListBoxTest object, cast to IEnumerator.

Putting the enumeration responsibility into a dedicated class that implements IEnumerator (ListBoxEnumerator) is generally preferred to the alternative of letting the collection class (ListBoxTest) know how to enumerate itself. The specialized enumeration class encapsulates the responsibility of enumeration and the collection class (ListBoxTest) is not cluttered with a lot of enumeration code.

1 comment:

  1. I've seen examples where people implement the enumerator as a nested class.

    I can't understand how this works? Why isn't the enumerator out of scipe for anyone trying to consme it?

    ReplyDelete