Author : Rahul
Last Modified : 12-Sep-2021
Complexity : Beginner

IEnumerable and IEnumerator Interface in C#


Introduction

There are two interface named IEnumerable and IEnumerator which are used to implement iteration in .Net. Iteration means you can use foreach loop to access all the elements of the collection one by one. Any class who implement these interfaces can be iterated. Since List, Dictionary etc implements IEnumerable interface so that the data within these can be iterated.

First we try to find the problem without these interfaces after that we analyse these two interfaces and at last we implement these two interfaces on custom class so that we can iterate over the collection of elements.

 

Problem without these Interfaces

Suppose we have one Customer class which contains country list from where orders has been placed by the customer. To print all these countries, we need to write below code.

Code

using System;

namespace IEnumerableAndIEnumerator
{
   class Customer
   {
       public string[] OrderCountryList = new string[10];
       int index = 0;
       
       public void AddCountry(string country)
       {
           OrderCountryList[index++] = country;
       }
       
       public void RemoveCountry(int index)
       {
           OrderCountryList[index] = "";
       }
   }
   
   class Program
   {
       static void Main(string[] args)
       {
           Customer customerOrderCountry = new Customer();
           customerOrderCountry.AddCountry("India");
           customerOrderCountry.AddCountry("Japan");
           customerOrderCountry.AddCountry("Britain");
           
           foreach (string country in customerOrderCountry.OrderCountryList)
           {
               Console.WriteLine(country);
           }
           
           Console.ReadKey();
       }
   }
}

Output

India
Japan
Britain

At initially this code look sufficient but there is one problem with the code. It display the internal structure of the class. It shows that Customer class contains one property named OrderCountryList which hold the country list. This is the violation of information hiding principle. If we make OrderCountryList as private then we will unable to access this property from outside.

To solve this problem we will use IEnumerable and IEnumerator Interface. These two interfaces provide a way to iterate over the object without the need of access modifier.
 

First we will analyse these two interfaces and after that we will implement these two interfaces on Customer class.

 

IEnumerable Interface

IEnumerable Interface is used to implement iteration. It contains one method named GetEnumerator. This method return the data of type IEnumerator Interface. It allow read only access to a collection.

GetEnumerator

This method is used to return the data of type IEnumerator. It allow read only access to a collection.

Syntex

public IEnumerator GetEnumerator()
{
   throw new NotImplementedException();
}

Example

public class Customer : IEnumerable  
{  
   public IEnumerator GetEnumerator()  
   {  
       throw new NotImplementedException();  
   }  
}

 

IEnumerator Interface

IEnumerator Interface is used to get current element from the collection. It contains two methods named MoveNext and Reset and one property named Current. This property is used to get current element from the collection.

MoveNext

This method is used to Set the enumerator to the next element of the collection. If the enumerator successfully set the next element of the collection it returns true and if the enumerator reached the end of the collection it returns false.
Syntex

public bool MoveNext()  
{  
   throw new NotImplementedException();  
}

Example

public class Customer : IEnumerator  
{  
   public bool MoveNext()  
   {  
       throw new NotImplementedException();  
   }   
}

 

Reset

This method is used to set the enumerator to the first element of the collection.

Syntex

public void Reset()  
{  
   throw new NotImplementedException();  
} 

Example

public class Customer : IEnumerator  
{  
   public void Reset()  
   {  
       throw new NotImplementedException();  
   }  
}

 

Current

This property is used to return the current element of the collection.

Syntex

public object Current  
{  
   get { throw new NotImplementedException(); }  
}  

Example

public class Customer : IEnumerator  
{  
   public object Current  
   {  
       get { throw new NotImplementedException(); }  
   }   
}


 

Implement IEnumerable and IEnumerator Interface

First we will implement IEnumerable Interface in our code. The IEnumerable Interface has one method named GetEnumerator(). The GetEnumerator method returns the object of child class which implements the IEnumerator interface. The IEnumerator has two methods, MoveNext() and Reset().

Code

using System;
using System.Collections;

namespace IEnumerableAndIEnumerator
{
   class Customer : IEnumerable
   {
       private string[] OrderCountryList = new string[10];
       int index = 0;
       
       public void AddCountry(string country)
       {
           OrderCountryList[index++] = country;
       }
       
       public void RemoveCountry(int index)
       {
           OrderCountryList[index] = "";
       }
       
       public IEnumerator GetEnumerator()
       {
           return new CustomerEnumerator();
       }
       
       class CustomerEnumerator : IEnumerator
       {
           public object Current => throw new NotImplementedException();
           
           public bool MoveNext()
           {
               throw new NotImplementedException();
           }
           
           public void Reset()
           {
               throw new NotImplementedException();
           }
       }
   }
   
   class Program
   {
       static void Main(string[] args)
       {
           Console.ReadKey();
       }
   }
}

Finally we will implement the logic for iterating.

Code

using System;
using System.Collections;

namespace IEnumerableAndIEnumerator
{
   class Customer : IEnumerable
   {
       private string[] OrderCountryList = new string[10];
       int index = 0;
       
       public void AddCountry(string country)
       {
           OrderCountryList[index++] = country;
       }
       
       public void RemoveCountry(int index)
       {
           OrderCountryList[index] = "";
       }
       
       public IEnumerator GetEnumerator()
       {
           return new CustomerEnumerator(ref OrderCountryList);
       }
       
       class CustomerEnumerator : IEnumerator
       {
           int index = -1;
           string[] OrderCountryList;
           
           public CustomerEnumerator(ref string[] countryList)
           {
               OrderCountryList = countryList;
           }
           
           public object Current
           {
               get { return OrderCountryList[index]; }
           }
           
           public bool MoveNext()
           {
               index++;
               return index >= OrderCountryList.Length ? false : true;
           }
           
           public void Reset()
           {
               index = -1;
           }
       }
   }
   
   class Program
   {
       static void Main(string[] args)
       {
           Customer customerOrderCountry = new Customer();
           customerOrderCountry.AddCountry("India");
           customerOrderCountry.AddCountry("Japan");
           customerOrderCountry.AddCountry("Britain");
           
           foreach (string country in customerOrderCountry)
           {
               Console.WriteLine(country);
           }
           
           Console.ReadKey();
       }
   }
}

Output

India
Japan
Britain