Iterator Design Pattern in C#

Iterator Design Pattern in C# with Examples

In this article, I am going to discuss the Iterator Design Pattern in C# with Examples. Please read our previous article where we discussed the basics of Behavioral Design Patterns in C#. The Iterator Design Pattern falls under the category of Behavioral Design Pattern. As part of this article, we are going to discuss the following pointers.

  1. What is Iterator Design Pattern?
  2. Example to understand the Iterator Design Pattern in C#.
  3. When to use the Iterator Design Pattern in C#?
What is Iterator Design Pattern?

The Iterator Design Pattern allows sequential access to elements without exposing the inside logic. That means using the Iterator Design Pattern we can access the elements of a collection in a sequential manner without knowing its internal representations.

The collections in C# like List, ArrayList, Array, etc. are nothing but containers that contain lots of objects. In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the elements of the container. Please have a look at the following image for a better understanding of the Iterator Design Pattern.

Iterator Design Pattern in C# with Examples

The point that you need to remember is that the Data structure of the List will be different from the Data Structure of ArrayList and the same in the case of an Array. That means the storing mechanism of List will be different from the storing mechanism of Array as well as different from the storing mechanism of ArrayList in C#.

So, the main use of the Iterator Design Pattern is to access the elements (object1, object2, object3, object4, etc.) of a collection (i.e. List, ArrayList, Array, etc.) in a sequential manner.

We use iterators quite frequently in our daily life. For example remote control of the TV. Remote control that we use, just pick up the TV remote control and start pressing the Up and Down or Forward and Back keys to iterate through the channels.

Example to understand the Iterator Design Pattern in C#:

Suppose we have a collection of employees. Then we can easily iterate through the collection using either for or for each loop in C# as shown in the below code.

Example to understand the Iterator Design Pattern in C#

Here, the for-each loop sequentially accesses the elements from the collection without exposing the internal logic i.e. how it is accessing the elements of the collection sequentially. Again, if you want to use a different data structure then you need to change the client code. Is not it nice to provide a uniform interface for traversing different collections?

For example, you may have different types of collections in your application such as List, Array, ArrayList, Generic Dictionary, etc. For whichever type of collection you have, you will need to traverse or iterate through the elements of the collections in a sequential manner. The actual implementation of how to traverse different types of collections will be different, yet the client code should not be concerned about the details of the implementations. The Iterator Design Pattern helps you to hide such details and provides a generic interface for the client to traverse different types of collections as shown in the below image.

Understanding the Iterator Design Pattern in C#

Let us see the step-by-step implementation to achieve the above using the Iterator Design Pattern in C#.

Step 1: Create the Collection Item

Here we are going to use the following Employee class as the item of our collection. So, create a class file with the name Employee.cs and then copy and paste the following code into it. The following Employee class is very straightforward. We have just created two properties and a constructor to initialize those two properties.

namespace IteratorDesignPattern
{
    // Collection Item
    class Elempoyee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public Elempoyee(string name, int id)
        {
            Name = name;
            ID = id;
        }
    }
}
Step 2: Creating Aggregate

This is going to be an interface that defines an operation to create an iterator object. Create a class file with the name IAbstractCollection.cs and then copy and paste the following code into it. The following interface declares one method i.e. CreateIterator which is going to create an Iterator object.

namespace IteratorDesignPattern
{
    // Aggregate Interface
    interface IAbstractCollection
    {
        // The following Method is going to Return an Iterator object.
        // Later, we will Implement the Iterator class
        Iterator CreateIterator();
    }
}

Here, we define one method which is going to be implemented by the ConcreteAggregate class to return the Iterator object.

Step 3: Creating ConcreteAggregate 

Create a class file with the name ConcreteCollection.cs and then copy and paste the following code into it. This class implements the AbstractCollection interface to return an instance of the proper Concrete Iterator class i.e. an instance of the Iterator class. The following class code is self-explained, so please go through the comment lines for a better understanding.

using System.Collections.Generic;
namespace IteratorDesignPattern
{
    // ConcreteAggregate Class
    // The following class going to implement the Iterator interface to return an instance of the proper ConcreteIterator
    class ConcreteCollection : IAbstractCollection
    {
        //The following collection object is going to hold a list of items or elements
        private List<Elempoyee> listEmployees = new List<Elempoyee>();

        //Implementing the CreateIterator method of the IAbstractCollection interface
        //The following method is going to Create and return the Iterator Object
        //Later we will implement the Iterator
        public Iterator CreateIterator()
        {
            return new Iterator(this);
        }
        
        // The following method is going to return the count of the elements present in the collection
        public int Count
        {
            get { return listEmployees.Count; }
        }

        //Add items to the collection
        public void AddEmployee(Elempoyee employee)
        {
            listEmployees.Add(employee);
        }

        //Get items from the collection based on the Index Position
        //Index is started from 0
        public Elempoyee GetEmployee(int IndexPosition)
        {
            return listEmployees[IndexPosition];
        }
    }
}
Step 4: Creating Abstract Iterator

Create a class file with the name AbstractIterator.cs and then copy and paste the following code into it. This is going to be an interface defining the operations for accessing and traversing elements in a sequence. Here, you can see, we have declared two methods i.e. First and Next, and one property with only get accessor. This interface is needed to be implemented by the Concrete Iterator Class and needs to provide implementations for these methods and properties.

namespace IteratorDesignPattern
{
    // Iterator Interface
    // This is going to be an interface defining the operations for accessing and traversing elements in a sequence.
    interface IAbstractIterator
    {
        Elempoyee First();
        Elempoyee Next();
        bool IsCompleted { get; }
    }
}
Step 5: Creating Concrete Iterator

Create a class file with the name Iterator.cs and then copy and paste the following code into it. This is going to be a concrete class implementing the Iterator interface and providing implementations for Iterator interface methods. This class also keeps track of the current position of the element in the traversal. The following class code is self-explained, so please go through the comment lines for a better understanding.

namespace IteratorDesignPattern
{
    // ConcreteIterator Class
    class Iterator : IAbstractIterator
    {
        //ConcreteAggregate variable to hold the collection elements
        private ConcreteCollection Collection;

        //The following variable is used as the Index Position 
        //to access the elements of the collection
        private int Current = 0;

        //The following variable is used to move to the next element from the current element
        private readonly int Step = 1;

        // Constructor
        public Iterator(ConcreteCollection Collection)
        {
            //Initializing the ConcreteAggregate variable using Constructor
            this.Collection = Collection;
        }

        // Gets First Item from the Collection
        public Elempoyee First()
        {
            //Setting Current as 0 to access the First Element of the Sequence
            Current = 0;
            return Collection.GetEmployee(Current);
        }

        // Gets Next Item from the Collection
        public Elempoyee Next()
        {
            //Increase the Current Index Position by step (Step = 1), 
            //to access the Next Element from the collection
            Current += Step;
            if (!IsCompleted)
            {
                return Collection.GetEmployee(Current);
            }
            else
            {
                return null;
            }
        }

        // Check whether the iteration is complete
        public bool IsCompleted
        {
            //When Current >= Collection.Count, means we have accessed all the elements
            get { return Current >= Collection.Count; }
        }
    }
}

The First method is used to return the First element from the collection. The current property is used to hold the index position of the current element. The Next method is used to return the next element from the collection by adding a step with the current value. The IsCompleted method is used to check whether the iteration is completed or not.

Step 6: Client Code

In our example, the Main method of the Program class is going to be the Client. So, in order to test whether everything is working as expected, please modify the Main method of the Program class as shown below.

using System;
namespace IteratorDesignPattern
{
    public class Program
    {
        static void Main()
        {
            // Build a collection
            ConcreteCollection collection = new ConcreteCollection();

            collection.AddEmployee(new Elempoyee("Anurag", 100));
            collection.AddEmployee(new Elempoyee("Pranaya", 101));
            collection.AddEmployee(new Elempoyee("Santosh", 102));
            collection.AddEmployee(new Elempoyee("Priyanka", 103));
            collection.AddEmployee(new Elempoyee("Abinash", 104));
            collection.AddEmployee(new Elempoyee("Preety", 105));
            
            // Create iterator
            Iterator iterator = collection.CreateIterator();

            //looping iterator      
            Console.WriteLine("Iterating over collection:");
            
            for (Elempoyee emp = iterator.First(); !iterator.IsCompleted; emp = iterator.Next())
            {
                Console.WriteLine($"ID : {emp.ID} & Name : {emp.Name}");
            }
            Console.Read();
        }
    }
}
Output:

Why do we need to use the Iterator Design Pattern in C#?

Iterator Design Pattern UML or Class Diagram

Let us understand the Class Diagram or UML Diagram of the Iterator Design Pattern. Please have a look at the following image.

UML or Class Diagram

As you can see in the above image, the Iterator Design Pattern consists of five components. They are as follows:

  1. Iterator (IAbstractIterator): This is going to be an interface defining the operations for accessing and traversing elements in a sequence. In our example, it is the IAbstractIterator interface.
  2. ConcreteIterator (Iterator): This is going to be a concrete class implementing the Iterator interface and providing implementations for Iterator interface methods. This class also keeps track of the current position of the element in the traversal. In our example, it is the Iterator class.
  3. Aggregate (IAbstractCollection): This is going to be an interface that defines an operation to create an iterator object. In our example, it is the CreateIterator() method of the IAbstractCollection interface.
  4. ConcreteAggregate (ConcreteCollection): This is going to be a concrete class that implements the AbstractCollection interface to return an instance of the proper Concrete Iterator class i.e. an instance of the Iterator class. In our example, it is the ConcreteCollection class.
  5. Client: This is the class that going to use the Iterator and Aggregate interfaces and access the elements. In our example, it is the Main method of the Program class.
Why do we need to use the Iterator Design Pattern in C#?

The Iterator Design Pattern in C# allows us to Access the elements of a collection without exposing its internal data structure. That means it allows you to navigate through a different collection of data using a common interface without knowing about their underlying implementation.

In the next article, I am going to discuss the Observer Design Pattern in C# with Examples. Here, in this article, I try to explain the Iterator Design Pattern in C# with examples. I hope you understood the need for and use of the Iterator Design Pattern in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *