Collection initializer and IEnumerable

Question | May 20, 2016 | hlone 

Collection Initializer ( {....} ) is a convenient way to initialize a collection. E.g:

List<int> lst  = new List<int> { 1 ,2 , 3 };

What if we want to support collection initializer for our custom collection class? In order to support collection initializer a class must implement IEnumerable and define an Add method. Here is an example implementation of a circular list class that implements IEnumerable....IEnumerator pattern:

using System;
using System.Collections;
using System.Collections.Generic;
class CircularList<T> : IEnumerable<T> {

  public CircularList(uint size) {
      list = new T[size==0 ? 1 : size];
  }
  public void Add(T t) {
      list[++lastIndex % list.Length] = t;
  }
  // IEnumerable<T>.GetEnumerator
  public IEnumerator<T> GetEnumerator() {
      for(int i=0; i<list.Length; ++i)
        yield return list[i];
  }
  /* IEnumerable.GetEnumerator
     calls generic GetEnumerator */
  IEnumerator IEnumerable.GetEnumerator() {
     return this.GetEnumerator();
  }

  private T[] list;
  private int lastIndex=-1;
}

The IEnumerable<T>.GetEnumerator method is supposed to return an IEnumerator, which is an iterator. Some C# constructs like foreach loop and collection initializer use iterators. You can either implement your own custom IEnumerator class or you can use the magical yield return/break statement, which C# compiler automatically compiles to an iterator. A function or method that uses yield return/break is called an iterator block.

Let's use our CircularList in an example and try to answer a question:

// Use iterator and Add method to initialize
var ct = new CircularList<int>(4) {
           1,2,3,4,5,6
};
// Use iterator to loop through and print
foreach(var i in ct)
    Console.Write( i+" " );

What would be the output of above?