Monday 14 August 2017

IEnumerable VS IEnumerator in C#

Introduction

First let's see a small demonstration of both of these interfaces and then we will talk about the differences.

DEMO

Create a new console application and in the main method add the following.
  1. static void Main(string[] args)
  2. {  
  3.    List<string> Month = new List<string>();  
  4.    Month.Add("January");  
  5.    Month.Add("February");  
  6.    Month.Add("March");  
  7.    Month.Add("April");  
  8.    Month.Add("May");  
  9.    Month.Add("June");  
  10.    Month.Add("July");  
  11.    Month.Add("August");  
  12.    Month.Add("September");  
  13.    Month.Add("October");  
  14.    Month.Add("November");  
  15.    Month.Add("December");  
  16. }  
In our main method, we created a new list collection “Month” of type string. In this collection we added all the 12 months as items in this list.

Note: The List class is present in the System.Collections.Generic namespace.

Now let's create a very simple IEnumerable on this list.
  1. //create IEnumerable of string  
  2. IEnumerable<string> iEnumerableOfString = (IEnumerable<string>)Month;  
  3.   
  4. //If we want to retrieve all the items from this IEnumerable object, we can use a foreach loop. 

  5. foreach(string AllMonths in iEnumerableOfString)
  6. {  
  7.    Console.WriteLine(AllMonths);  
  8. }  
Run the application.


We got the list of months.

Now let's see how to do the same, using an IEnumerator and then we will see the differences.
  1. //Create IEnumerator of string.
     
     
  2. IEnumerator<string> iEnumeratorOfString = Month.GetEnumerator();//to convert list into IEnumerator we can invoke the GetEnumerator method  
  3.   
  4. //To retrieve all the items from the above IEnumerator object, we cannot use foreach loop instead of that we need to invoke MoveNext() Boolean method.  
  5. while(iEnumeratorOfString.MoveNext()) 
  6. {  
  7.   
  8. }  
To display the items on the console window we need to invoke the Current property as in the following:
  1. while(iEnumeratorOfString.MoveNext())  
  2. {  
  3.    Console.WriteLine(iEnumeratorOfString.Current);  
  4. }  
Run the application.



Similarities

Both of these interfaces help to loop through the collection.

So, now the next question is, what should I use?

As we know, both of these interfaces give the same result. But if you watch the syntax for IEnumerable, it is very simple.
  1. foreach(string AllMonths in iEnumerableOfString)  
  2. {  
  3.    Console.WriteLine(AllMonths);  
  4. }  
But in the case of IEnumerator, we need to invoke the MoveNext method and to retrieve the current item, we need to invoke the current property.

Relation
The IEnumerable interface actually uses IEnumerator. The main reason to create an IEnumerable is to make the syntax shorter and simpler.

If you go to the definition of the IEnumerable<T> interface, you will see this interface has a method GetEnumerator() that returns an IEnumerator object back.


In short, this IEnumerable uses IEnumerator internally.

Differences
The main difference between IEnumerable and IEnumerator is an IEnumerator retains its cursor's current state.

Let's understand this practically.

Create two static methods in the main program.
  1. static void iEnumeratorMethodOne(IEnumerator<string> i)  
  2. {  
  3.    while(i.MoveNext())  
  4.    {  
  5.       Console.WriteLine(i.Current);  
  6.   
  7.        if(i.Current == "June")  
  8.        {  
  9.           iEnumeratorMethodTwo(i);  
  10.        }  
  11.     }  
  12. }  
  13.   
  14. static void iEnumeratorMethodTwo(IEnumerator<string> i)  
  15. {  
  16.     while(i.MoveNext())  
  17.     {  
  18.        Console.WriteLine(i.Current);  
  19.      }  
  20. }  
Explanation
  1. In the iEnumeratorMethodOne method, we added a parameter “i” of type IEnumerator of string.
  2. Inside the method block, we used a while loop to move to the next item using the MoveNext method and if the item is found then we invoked the Current property that will provide us the current item and we are displaying that item on the console window.
  3. In the if block we are checking the current item state, if the item is “June” then we invoke the second iEnumerator method and in that method we passed the IEnumerable of string object. In other words, i.
    Then invoke this method in the main method and pass an iEnumeratorOfString as a parameter argument.
  1. IEnumerator<string> iEnumeratorOfString = Month.GetEnumerator();  
  2. iEnumerableMethodOne(iEnumeratorOfString);  
Put a breakpoint on both the iEnumeratorMethods and press F10.

Look at the current item; it is January.
In the if block, the current item is being compared with the item “June”. Once the current item is June then it will invoke the second method.

Press F10 until the current item reaches June.



So, now the current item is June which means the if block will be executed and this block will invoke iEnumeratorMethoTwo.


Look at the current item present in the i object, “June”.

Once this iEnumeratorMethoTwo executes, look at the current item.


It's July.



Then August and so on.

So, IEnumerator retains its cursor state.

In the end we will get the following result.



So, if you want to loop sequentially through the collection, use an IEnumerable interface else if you want to retain the cursor position and want to pass it from one function to another function then use an IEnumerator interface.

No comments:

Post a Comment