Hot off the presses... What do you think?

 ..brad

Implementing IEnumerable

Almost all collections expose some way to enumerate elements it contains.  The IEnumerable interface encapsulates this notion such that common facilities can be built that work on any kind of collection.   These guidelines apply to any type implementing ICollection, IList or IDictionary as well. 

?     Do see the generics guidelines in section x.y (tbd)

?     Do see section 11 for more collections guidelines

?     Do implement IEnumerable on any type that can be enumerated

?      Do name the class ItemTypeCollection for implementations that contain homogenous types. Such as StringCollection, EmployeeCollection, etc

?     Do explicitly implement IEnumerable.GetEnumerator()

?     Do provide a GetEnumerator() method that returns a nested public struct called “Enumerator”

Rationale: the foreach language construct will prefer calling the method named GetEnumerator (that follows the enumerator pattern) rather than the interface method which means there will be one less GC heap allocation each time the collection is enumerated.     

?     Do explicitly implement the IEnumertor.Current property on the Enumerator struct

?     Do provide a strongly typed Current property that returns the item type on the Enumerator struct

Rationale: If item type is a value type this avoids a boxing operation each time through the loop.  If item type is a reference type there is a small savings for not having to do the cast.

?     Avoid having members on your collection be virtual unless extensibility is truly required

Rationale: The JIT is not able to inline calls to virtual methods.  

These guidelines lead to this pattern…

public class  ItemTypeCollection: IEnumerable

{

   public struct Enumerator : IEnumerator

   {

      public ItemType Current { get {… } }

      object IEnumerator.Current { get { return Current; } }

      public bool MoveNext() { … }

      …

   }

   public Enumerator GetEnumerator() { … }

   IEnumerator IEnumerable.GetEnumerator() { … }

   …

}

Tradeoff: Implementing this pattern involves having an extra public type (the Enumerator) and several extra public methods that are really there just for infrastructure reasons.  These types add to the perceived complexity of the API and must be documented, tested, versioned, etc.  As such this pattern should only be followed where performance is paramount.  

?     Prefer implementing IEnumerable interface with optimistic concurrency

Rationale:  There are two legitimate ways to implement the IEnumerable interface.  The first is to assume that the collection will not be modified while it is being enumerated.  If it is modified throw an InvalidOperationException exception.  The 2nd way is to make a snap-shot of the collection in the enumerator thus isolating the enumerator from changes in the underlying collection.  For most usages for enumerable.  For most general usage scenarios the optimistic  concurrency model provides net better performance.