How to Use the Iterator Pattern in C#

Written by ssukhpinder | Published 2021/06/08
Tech Story Tags: programming | csharp | dotnet | design-patterns | dotnet-core | oop | software-architecture | aspnetcore | web-monetization

TLDR An example of a collection list of cars and an array of motorcycles is an example of the use case. According to Gang of Four, the iterator pattern provides a process to obtain the aggregator object without knowing its implementation. The article demonstrates the usage of the design pattern using the C# programming language. The PrintVehicles methods check if!iterator.isDone then output the collection element. The printVehicles method check if.receive!iterator is done, and output the. element.via the TL;DR App

According to Gang of Four, the iterator pattern provides a process to obtain the aggregator object without knowing its implementation.

Use Case

Let us take an example of a collection list of cars and string[] an array of motorcycles; we need to design an aggregator object to iterate over the collection without knowing whether it's a list or an array.
The iterator design pattern helps solve this problem wherein a standard iterator will traverse different collection types.

Prerequisites

  • Basic knowledge of OOPs concepts.
  • Any programming language knowledge.
The article demonstrates the usage of iterator design patterns using the C# programming language.

Getting Started

Considering the above use case, let us define a custom iterator interface that acts as an abstract layer over the list and array iterator.
public interface IVehicleIterator{
  void First();
  bool IsDone();
  string Next();
  string Current();
}
Now write car and motorcycle iterators that implement the above interface according to the use case.

CarIterator.cs

The car iterator is implemented over
List<string>
collection and provides an implementation of interface methods.
public class CarIterator : IVehicleIterator
{
    private List<string> _cars;
    private int _current;
    public CarIterator(List<string> cars)
    {
        _cars = cars;
        _current = 0;
    }
    public string Current()
    {
        return _cars.ElementAt(_current);
    }

    public void First()
    {
        _current = 0;
    }

    public bool IsDone()
    {
        return _current >= _cars.Count;
    }

    public string Next()
    {
        return _cars.ElementAt(_current++);
    }
}

MotorcycleIterator.cs

The motorcycle iterator is implemented over 
string[]
 collection and provides an implementation of interface methods.
public class MotercycleIterator : IVehicleIterator
{
    private string[] _motercylces;
    private int _current;
    public MotercycleIterator(string[] motercylces)
    {
        _motercylces = motercylces;
        _current = 0;
    }
    public string Current()
    {
        return _motercylces[_current];
    }

    public void First()
    {
        _current = 0;
    }

    public bool IsDone()
    {
        return _current >= _motercylces.Length;
    }

    public string Next()
    {
        return _motercylces[_current++];
    }
}
After all the above iterators are defined, define a standard aggregator object interface that creates iterators.
public interface IVehicleAggregate{
   IVehicleIterator CreateIterator();
}
Finally, write down the classes which implement the above aggregator interface. According to the use-case, both Car and Motorcycle classes will implement the aggregator interface.

Car.cs

The method of aggregator interface returns the relevant iterator as shown below.
public class Car : IVehicleAggregate
{
    private List<string> _cars;
    public Car()
    {
        _cars = new List<string> { "Car 1", "Car 2", "Car 3" };
    }

    public IVehicleIterator CreateIterator()
    {
        return new CarIterator(_cars);
    }
}

Motorcycle.cs

The method of aggregator interface returns the relevant iterator as shown below.
public class Motercycle : IVehicleAggregate
{

    private string[] _motercycles;
    public Motercycle()
    {
        _motercycles = new[] { "Bike 1", "Bike 2", "Bike 3" };
    }
    public IVehicleIterator CreateIterator()
    {
        return new MotercycleIterator(_motercycles);
    }
}

Iterator Pattern in Action

static void Main(string[] args)
{
    IVehicleAggregate car = new Vehicles.Car();
    IVehicleAggregate motercycle = new Vehicles.Motercycle();

    IVehicleIterator carIterator = car.CreateIterator();
    IVehicleIterator motercycleIterator = motercycle.CreateIterator();

    PrintVehicles(carIterator);
    PrintVehicles(motercycleIterator);
}

static void PrintVehicles(IVehicleIterator iterator)
{
    iterator.First();
    while (!iterator.IsDone())
    {
        Console.WriteLine(iterator.Next());
    }
}
The PrintVehicles methods check if 
!iterator.isDone
 then output the collection element. No matter what collection we’re dealing with, implement methods like First, IsDone, and Next.

Output

We don’t know the underlying collection type, but it is still iterated over it via Iterator Design Pattern. If you go ahead and run, it displays the following output:
Thank you for reading, and I hope you liked the article. Please provide your feedback in the comment section.
Also published on Medium's subdomain.

Written by ssukhpinder | Programmer by heart | C# | Python | .Net Core | Xamarin | Angular | AWS
Published by HackerNoon on 2021/06/08