IEnumerable and IEnumerator in C#

IEnumerable and IEnumerator are both interfaces in C#. Now, what exactly are these? Why are they used? Are they associated with each other? What is the difference between them? Let’s find out the answers to each of these questions one by one in this article.

IEnumerable

IEnumerable is an interface available in System.Collections namespace that is the base interface for all the collections that are non-generic and can be enumerated. It can also be used to loop over generic collections. The IEnumerable interface contains just one method called ‘GetEnumerator’ that returns an instance of IEnumerator interface that iterates through a collection.

The IEnumerable interface looks something like this:

    public interface IEnunmerable
    {
         IEnumerator GetEnumerator () ;
    }

The implementation of GetEnumerator() method of IEnumerable is as follows:

    IEnumerator IEnumerable.GetEnumerator () {
        return (IEnumerator) GetEnumerator ();
    }

IEnumerable interface also has some extension methods in C#

  1. AsParallel ( IEnumerable ) : It enables the parallelization of a  query .
  2. AsQueryable ( IEnumerable ) : It converts an IEnumerable to an IQueryable .
  3. Cast <TResult> ( IEnumerable ) : It casts the elements of an IEnumerable to the specified type.
  4. OfType <TResult> ( IEnumerable ) : It filters the elements of an IEnumerable based on a specified type.

Another question that could arise is ‘How is IEnumerable different from a list?’

Well, IEnumerable essentially defines a behaviour. Using IEnumerables allows you to use for each i.e it allows to loop over all the data present. This is very useful especially in cases such as when you a have a large amount of data in your database and you don’t want to waste your memory by storing all this data in it. Instead, you just want to read through the entire data unlike lists. Another advantage of IEnumerable over list is the differed execution. The query will not get executed until you loop through the data.

In C#, collections such as stacks, queues, lists, dictionaries, etc. are all already implemented as IEnumerable interfaces and can be iterated over the items in these collections with the help of foreach.

IEnumerator

IEnumerator , as mentioned above , is an interface that , helps you reach the current element from the collection. It is the base interface for all non-generic enumerators.

The complexity of enumerators hide under the foreach statement and due to this reason it is always advised to use the foreach loop instead of manipulating the enumerators. Enumerators can be used to read the data inside a collection but cannot be used to modify the underlying data in a collection.

The IEnumerator has a property called ‘current’ that helps in getting the current element and contains the following 2 methods:

  1. MoveNext () method
  2. Reset () Method

MoveNext  () : The MoveNext method is used to set the enumerator to the following element of the collection. It returns true if the enumerator is set to the next element of the collection successfully and false when the enumerator reaches the end of the collection.

Reset () : The Reset method, as the name suggests, resets the position of the enumerator to the very beginning of the collection i.e. before the first element of the collection (the initial position of the enumerator)

Here’s what the implementation of the IEnumerator interface looks like:

   public object Current {
      get { throw new NotImplementedException (); }
   }
   
   // IEnumertor method
   public bool MoveNext () {
      throw new NotImplementedException ();
   }
   
   // IEnumertor method
      public void Reset  () {
      throw new NotImplementedException ();
   }

Implementation of IEnumerable and IEnumerator Interfaces

To perform iteration over custom collection classes (such as Stacks, Queues, Lists, Dictionaries, etc.), the implementation of both, IEnumerable and IEnumerator interfaces is required.

Let us look at the following example to understand better.

using System;
using System.Collections;

namespace IEnumerableandIEnumerator
{
    class Example
    {
       static void Main(string[] args)
       {
          PeopleData[] pData = new PeopleData [6] {
          new PeopleData ( 1, "Edward", "Germany"),
          new PeopleData ( 2, "Louis", "England"),
          new PeopleData ( 3, "Elizabeth", "Ireland"),
          new PeopleData ( 4, "Payton", "USA"),
          new PeopleData ( 5, "Delilah", "Italy"),
          new PeopleData ( 6, "Venessa", "Norway")
          };

          People peep = new People ( pData ) ;
          foreach ( var p in peep )
          {
            Console.WriteLine (p.Number + ", " + p.Firstname + ", " + p.Place ) ;
          }
          Console.ReadLine();
       }
    }
    
    public class PeopleData
    {
       public PeopleData ( int number, string firstname, string place )
       {
          this.Number = number ;
          this.Firstname = firstname ;
          this.Place = place ;
       }
       public int Number { get ; set ; }
       public string Firstname { get ; set ; }
       public string Place { get ; set ; }
    }
    
    //Implements IEnumerable Interface
    public class People : IEnumerable
    {
       private PeopleData [] _p;
       public People( PeopleData  [] pArray )
       {
          _p = new PeopleData[ pArray.Length ] ;
          for ( int i = 0 ; i < pArray.Length ;  i++ )
          {
            _p [i] = pArray [i] ;
          }
       }
       IEnumerator IEnumerable.GetEnumerator ()
       {
          return (IEnumerator) GetEnumerator () ;
       }
       public PeopleEnum GetEnumerator ()
       {
          return new PeopleEnum(_p);
       }
    }
    
    // Implements IEnumerator Interface
    public class PeopleEnum : IEnumerator
    {
       public PeopleData [] _p;
       int currentIndex = -1;
       public PeopleEnum ( PeopleData [] list )
       {
         _p = list;
       }
       public bool MoveNext ()
       {
          currentIndex++;
          return ( currentIndex < _p.Length );
       }
       object IEnumerator.Current
       {
          get
          {
            return Current;
          }
       }
       public PeopleData Current
       {
         get
         {
           try
           {
              return _p [ currentIndex ] ;
           }
           catch ( IndexOutOfRangeException )
           {
              throw new InvalidOperationException () ;
           }
         }
       }
       public void Reset ()
       {
          currentIndex = -1;
       }
    }
}

The output of the above code will be –

1, Edward, Germany
2, Louis, England
3, Elizabeth, Ireland
4, Payton, USA
5, Delilah, Italy
6, Venessa, Norway

As we can see, in the above code, both IEnumerable and IEnumerator interfaces have been implemented in order to iterate on a non-generic collection called ‘People’.

Conclusion

So, in simple words , IEnumeratable is an interface that uses IEnumerator interface in order to iterate or loop over a non-generic collection.

Leave a Comment

Your email address will not be published.