Its been a long while since i wrote any single piece of information. But i have no apologies for that, but a big GRIN :D. I am assuming you had already read the Part 1 of this article. Also for those who are here just because of the heuristics of a search engine, i am sure you have a piece of PIE here.

In this article we will discuss

  1. How the foreach statement is able to fetch an item from the collection source
  2. Get an essence of a magic wand yield return

We will try to explain both of the above with the following example. There is a Gender class which will return the list of available Genders when enumerated. In the main function we create an instance of the Genders class and use for each to enumerate it.

Note that the class Genders is enumerable because it implements the Generic IEnumerable<T> interface. This interface exposes a GetEnumerator() method which returns a IEnumerator<T> object (here it returns IEnumerator<string>). So what is the point ? If you want to implement a class that should be enumerated, then it should implement the IEnumerable<T> interface.  The IEnumerator<T> is the actor that performs the iteration of the elements when the for each loop asks for a element of type T.  For your enumerable class you have to write your own Enumerator class that will implement the Generic IEnumerator<T> interface. Here the GenderEnumerator is the class that actually iterates the collection source and returns an object of type T.

   1: using System;
   2: using System.Linq;
   3: using System.Collections.Generic;
   4:  
   5: namespace EnumerableExample
   6: {
   7:     class Program
   8:     {
   9:         static void Main(string[] args)
  10:         {
  11:            foreach (var data in new Gender()) 
  12:                Console.WriteLine(data);
  13:         }
  14:     }
  15:  
  16:     class Gender : IEnumerable<string>
  17:     {
  18:         public string[] genders = { "Male", "Female"};
  19:         public Gender() { }
  20:  
  21:         public IEnumerator<string> GetEnumerator()
  22:         {
  23:             //return new GenderEnumerator(0){ obj = this};
  24:             yield return "Male";
  25:             yield return "Female";
  26:         }
  27:  
  28:         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  29:         {
  30:             return new GenderEnumerator(0) { obj = this };
  31:         }
  32:     }
  33:  
  34:  
  35:     class GenderEnumerator : IEnumerator<string>
  36:     {
  37:         public Gender obj;
  38:         int state;
  39:         public GenderEnumerator(int initialState)
  40:         {
  41:             this.state = initialState;
  42:         }
  43:         public string Current
  44:         {
  45:             get;
  46:             private set;
  47:         }
  48:  
  49:         public void Dispose(){ }
  50:  
  51:         #region IEnumerator Members
  52:  
  53:         object System.Collections.IEnumerator.Current
  54:         {
  55:             get { return this.Current; }
  56:         }
  57:  
  58:         #endregion
  59:  
  60:         public bool MoveNext()
  61:         {
  62:             if (state < this.obj.genders.Length)
  63:             {
  64:                 this.Current = this.obj.genders[state++];
  65:                 return true;
  66:             }
  67:             else
  68:                 return false;
  69:         }
  70:  
  71:         public void Reset()
  72:         {
  73:             state = 0;
  74:         }
  75:     }
  76:  
  77: }
 

QUESTION 1: How the for each statement is able to fetch an item from the collection source ?

When the statement foreach (var data in new Gender()) is compiled, the following things happen.

  1. The compiler will create an instance for the Gender class (new Gender()).
  2. Since Gender class is specified to be iterated, the compiler will check whether the class is Enumerable (i.e whether it extends IEnumerable<T> or IEnumerable). Any object that can be iterated should implement the IEnumerable<T>. (If that object implements IEnumerable<T> then no need to extend IEnumerable, since IEnumerable<T> extends IEnumerable , but however the user has to implement members of both the classes)
  3. var data is the holder for the item being returned by the enumerator. the actual type to substitute to var is inferred from the method GetEnumerator<T> inside the Gender class. For non generic versions it will be always substituted with object.

Now when the foreach is executed for the first time a new instance of the GenderEnumerator class is initiated and returned. Now this gender enumerator is the one which actually iterates through the collection and returns the value whenever the for each asks for an element. The property Current in the GenderEnumerator class gives the value for the for each statement and the MoveNext method changes the state of the enumerator to get the next available element in the collection.

The foreach in the above program in Line 11 can be changed something like the following.

            Gender genderClass = new Gender();
            IEnumerator<string> genderEnum = genderClass.GetEnumerator();
            while(genderEnum.MoveNext())
                Console.WriteLine(genderEnum.Current);

Now i hope you can understand how for each works. It internally iterates the collection using the MoveNext() method and uses the “Current” property to return data needed.

Now writing an IEnumerator<T> like the GenderEnumerator class mentioned above can be a arduous task for developers. So in C# there is a sugar candy for this, which we can almost call as a magic wand that wishes a dynamically created Enumerator for user defined enumerable classes. i.e the yield return keyword (You can switch you context into the mode of reading the answer for 2nd Question). The above program can be written as simple as the following. I just used a Syntactic based C# editor to make this program appear glamorously. This is more a pseudo code than a program. :)

Capture

Oh my god ! am i returning an IEnumerator<string> object from the GetEnumerator() method? or i had wrote or clipped some code that is crummy enough not to build successfully. I guess no. The yield return as we mentioned is useful enough to avoid writing a hamlet of code to return an IEnumerator<T> object, like we did in the previous example. When the above code is compiled and if you see the program in reflector then you will find something interesting….. as follows…..

    // Nested Types
    [CompilerGenerated]
    private sealed class <GetEnumerator>d__0 : IEnumerator<string>, IEnumerator, IDisposable
    {
        // Fields
        private int <>1__state;
        private string <>2__current;
        public Gender <>4__this;
    <span>// Methods</span>
    [DebuggerHidden]
    <span>public</span> &lt;GetEnumerator&gt;d__0(<span>int</span> &lt;&gt;1__state);
    <span>private</span> <span>bool</span> MoveNext();
    [DebuggerHidden]
    <span>void</span> IEnumerator.Reset();
    <span>void</span> IDisposable.Dispose();

    <span>// Properties</span>
    <span>string</span> IEnumerator&lt;<span>string</span>&gt;.Current &#123; [DebuggerHidden] get; &#125;
    <span>object</span> IEnumerator.Current &#123; [DebuggerHidden] get; &#125;
&#125;

 

The yield return keyword is transformed into private compiler generated class inside the Gender class. This class performs the same function of the gender enumerator class. Note that the members of both IEnumerable and IEnumerabe<T> are implemented to make this work in both with generic and non-generic clients. Hope you enjoyed the post. I am eager and happy to receive your comments.