The 70–536 skills matrix says that I need to know about the full set of collection interfaces inside the .NET Framework, specifically:

  • ICollection and IList
  • IComparer, IEqualityComparer and IKeyComparer
  • IDictionary and IDictionaryEnumerator
  • IEnumerable and IEnumerator
  • IHashCodeProvider

Rather than tackle these in order I will rearrange the list a little so it is a little bit more logical, first up the main interfaces!

IEnumerable, ICollection and IList

These three interfaces are the core of the collection system. IEnumerable defines one method called GetEnumerator which returns an object that implements IEnumerator. It is a generic mechanism where every object can work with the variety of “foreach” constructs in every language.

It supports forward only traversal over a set of objects – not only do you find it arrays and collection classes but you find it on other types such as System.String to allow you to enumerate over a block of text as a sequence of characters - very useful.

The ICollection interface actually inherits from the IEnumerable interface, so by definition everything an IEnumerable object can do an ICollection object can as well. What is different about the ICollection interface is that it represents a known quanitity of elements so that you can get a count of how many elements there are in the collection. It also introduces a number of properties to support synchronised access to elements (you lock on SyncRoot).

Introducing IList! I list inherits both ICollection and IEnumerable but adds a number of methods to support adding and removing items from the underlying collection of objects. In an amazing stroke of inconsistent naming you will find that most classes that implement IList are actually called somethingCollection, and not all those that have IList-like methods are actually IList implementors. The only reason I have to explain this inconsistency is history.

Many of the frameworks that Microsoft published in the past exposed collections of objects, and those collections were mutable with add and remove methods. I suspect that Microsoft could have called ControlCollection ControlList but the natives would have gotten restless.

IComparer, IEqualityComparer and IKeyComparer

These three interfaces are used in various ways by the collections framework in .NET. Take IComparer for example – it can be used to provide a sort ranking for any two objects. Now - there is a related interface called IComparable in which an element object can sort itself but it is fairly common for this interface not to be implemented so the IComparer gives you an external and more flexible mechanism for sorting.

One pattern that I used with comparers is to create one for each of my domain objects, then sub-class it for each of the various properties. These sub-classes then become accessible off the base domain object comparer as static properties (SortByLastName type stuff). If you want to get really fancy you can even make it support multi-property sorts by having the base comparer take a paramarray of sorts which it then applies sequentially to determine the ultimate sort order.

So thats IComparer – what about IEqualityComparer and IKeyComparer? Well IEqualityComparer is a special kind of comparer which is use to determine equality only – so it can’t really be used for sorts. Its reason for being is a bit fuzzy for me but from what I read the idea is that it is useful for culture aware comparisons where a straight string comparison wouldn’t work correctly. The MSDN documentation also had some interesting implementation notes:

“The Equals method is reflexive, symmetric, and transitive. That is, it returns true if used to compare an object with itself; true for two objects x and y if it is true for y and x; and true for two objects x and z if it is true for x and y and also true for y and z. Implementations are required to ensure that if the Equals method returns true for two objects x and y, then the value returned by the GetHashCode method for x must equal the value returned for y.”

Looks to me like a good candidate for a unit test whenever you implement one because it would be so easy to get one of those implementation details wrong and cause all kinds of wierdness.

IKeyComparer? OK – you could probably carbon date when this skills matrix was put together by the names of the interfaces and classes that no longer exist, but basically the IKeyComparer was slated to be renamed to IHashComparer. You can read about the change here on Krzysztof Cwalina’s blog – however, I suspect that this never happened and the interface has been dropped entirely.

IDictionary

The IList interface is all about storing a set of elements and making them indexable by a numerical key. The IDictionary interface expands the concept of having an index to access elements in a set by allowing you to define what that key value is. The IDictionary interface is kind of loose in that it allows us to use any key and any value as long as it derives from System.Object (now find me one that doesn’t). With the generic IDictionary<K,V> interface you can lock that down a little bit.

IEnumerator and IDictionaryEnumerator

Implementors of IEnumerator are returned from the GetEnumerator method from classes that implement IEnumerable. The interface defines two methods, Reset and MoveNext and a Current propertyly that allows you to grab the current element. The IDictionaryEnumerator is a specialisation of the IEnumerator interface for dictionary objects. It defines an additional three properties, Entry, Key and Value.

The Entry property is the same as Current on IEnumerator except it is hardwired to return a DictionaryEntry and the Key and Value properties just provide easier access to the the Key and Value properties of the DictionaryEntry instance returned by the Entry property (phew – what a mouthful).

Actually, one of the things that always gets me about working with dictionaries is that when I go to enumerate them in a “foreach” loop I get an InvalidCastException – its because I always think that I am just enumerating the values, not a set of DictionaryEntry instances.

IHashCodeProvider

The IHashCodeProvider interface has now been obsoleted and we should use IEqualityComparer instead (see above). I guess the theory behind this was that we shouldn’t allow people to get in and trash the hashing algorithm in classes like the Hashtable, instead we should give them a specific interface to implement for all the things that would normally make them take that drastic step.