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?