IEnumerable and IEnumerator in C#

C# Programming Guide

Most novice C# programmers find it difficult to understand the difference between IEnumerable and IEnumerator. In this C# programming tutorial, we will explain what these two interfaces are and what their significance is in C# programming and software development.

The two interfaces are defined in .NET for the purpose of iteration. By iteration, we mean that a programmer can access or traverse through all the elements of a collection. Any class that implements these interfaces can also be iterated. Note that, in .NET, all collection implement the IEnumerable interface. This means you can iterate over the data items of collections such as lists, stacks, dictionaries, and so forth.

Read: C# Tools for Code Quality

What is the IEnumerable Interface in C#

The IEnumerable interface is used to iterate a given object in C#. It contains a method called GetEnumerator. The method allows read-only access to the collection and returns the data of the type IEnumerable.

How to use GetEnumerator in C#

The GetEnumerator method is used for returning the data of type IEnumerator. Here is the syntax for using GetEnumerator:

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

Here is some example code showing how to use GetEnumerator in C#:

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

What is the IEnumerator Interface in C#?

The IEnumerator interface is used to fetch the current element from a collection. It contains a property called Current. Apart from a property, it also contains two methods, namely: MoveNext and Reset. We look at these two methods below and how to use them.

MoveNext Method in C#

To set the enumerator to the next element of a given collection, IEnumerator has a method called MoveNext(). The method will return false if the enumerator has reached the end of the collection, otherwise it will return true.

Here is the syntax of the MoveNext() method in C#:

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

Here is some example code showing how to use MoveNext() in a C# application:

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

Reset() Method in C#

You can call the Reset() method to set the enumerator to the first element of collection. Here is its syntax:

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

Here is an example of using the Rest() method in C#:

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

Read: Productivity Tools for .NET Developers

Current Property in C#

The Current property is used to return the current element of a collection. Here is the Current properties syntax:

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

Here is an example of how to use the Current property in C#

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

Use Cases for the IEnumerable and IEnumerator Interfaces

Let’s understand through a code example what the use cases are where these two interfaces can make the task of a programmer easier.

In the C# code example, let’s assume we have a class called Product that holds the information of all the products in an inventory. We would add and delete the items to and from our inventory by calling the AddProduct() and RemoveProduct() methods respectively and, finally, print all the products available.

using System;
namespace IEnumerableAndIEnumerator{
 
class Product
{
       public string[] ProductList = new string[5];
       int index = 0;
       
       public void AddProduct(string product)
       {
           ProductList[index++] = product;
       }
       public void RemoveProduct(int index)
       {
           ProductList[index] = "";
       }
   }
   
   class Program
   {
       static void Main(string[] args)
       {
           Product product = new Product ();
           product.AddProduct("Product A");
           product.AddProduct ("Product B");
           product.AddProduct ("Product C");
           foreach (string iteration in product.ProductList){
               Console.WriteLine(iteration);
           }
           
           Console.ReadKey();
       }
   }
}

If you run the above program in your integrated development environment (IDE) or code editor, you will get the following output:

Product A
Product B 
Product C

If you run the above program on your system it will work fine and print all those products. But wait – there is an issue with the code. Did you notice when we are using the foreach loop to iterate over the product list item, it exposes the internal structuring of the class?

foreach (string iteration in product.ProductList)
{
…
}

Our Product class contains one property called ProductList that holds all the products. You probably noted we have used this property outside of its class? However, this property should not be used in another class because doing so would violate one of the programming principles called Information hiding. One of the things we can do to make the property inaccessible is to set the access modifier of this property as private. But it would also not solve our problem, because that property would no longer be accessible outside of its class.

To solve this type of problem, the interfaces IEnumerable and IEnumerator come into play. Using these interfaces, you can easily iterate over the objects no matter what their access modifier is. In the following section, we will see how these interfaces are implemented.

Read: Project Management Software for .NET Developers

How to Implement IEnumerable and IEnumerator in C#

In this section, we will implement the IEnumerable and IEnumerator interfaces to solve the problem mentioned above:

using System;
using System.Collections;
namespace IEnumerableAndIEnumerator
{
   class Product : IEnumerable
   {
       public string[] ProductList = new string[5];
       int index = 0;
       
       public void AddProduct(string product)
       {
           ProductList[index++] = product;
       }
       public void RemoveProduct(int index)
       {
           ProductList[index] = "";
       }
       public IEnumerator GetEnumerator()
       {
           return new ProductEnumerator();
       }
       
       class ProductEnumerator : 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();
       }
   }
}

Here, we have implemented all the respective methods of both interfaces. So far so good. What we want to do next is write the logic for iteration over the product items. Note that we will be making use of a variable index that works as a pointer that points to the current element of ProductList:

using System;
using System.Collections;
 
namespace IEnumerableAndIEnumerator
{
      class Product : IEnumerable{
       public string[] ProductList = new string[5];
       int index = 0;
       
       public void AddProduct(string product)
       {
           ProductList[index++] = product;
       }
       public void RemoveProduct(int index)
       {
           ProductList[index] = "";
       }
       
       public IEnumerator GetEnumerator()
       {
           return new ProductEnumerator(ref ProductList);
       }
       
       class ProductEnumerator : IEnumerator
       {
           int index = -1;
           string[] ProductList;
           
           public ProductEnumerator(ref string[] productList)
           {
               ProductList = productList;
           }
           
           public object Current
           {
               get { return ProductList[index]; }
           }
           
           public bool MoveNext()
           {
               index++;
               return index >= ProductList.Length ? false : true;
           }
           
           public void Reset()
           {
               index = -1;
           }
       }
   }
   
   class Program
   {
       static void Main(string[] args)
       {
           Product product = new Product();
           product.AddCountry("Product A");
           product.AddCountry("Product B");
           product.AddCountry("Product C");
           
           foreach (string iteration in product)
           {
               Console.WriteLine(iteration);
           }
           
           Console.ReadKey();
       }
   }
}
 

And there we have it -we have successfully solved our issue by implementing the IEnumerable and IEnumerator interfaces into our C# code.

Read more C# programming tutorials and guides to software development.

Tariq Siddiqui
Tariq Siddiqui
A graduate in MS Computer Applications and a Web Developer from India with diverse skills across multiple Web development technologies. Enjoys writing about any tech topic, including programming, algorithms and cloud computing. Traveling and playing video games are the hobbies that interest me most.

More by Author

Must Read