Iterator Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases

Iterator Pattern in C#: Definition, Examples, Pros, Cons, and Use Cases

The Iterator pattern in C# is a behavioral design pattern that provides a way to sequentially access elements of a collection without exposing its internal structure.

The Iterator pattern allows clients to traverse collections without knowing how the collection is internally implemented. It separates collection management logic from traversal logic, improving encapsulation and maintainability. In C#, the pattern is commonly implemented using the IEnumerable and IEnumerator interfaces. An iterator maintains the current traversal state and provides methods for moving through elements one by one. This pattern is heavily used in collections, LINQ operations, file readers, tree traversal systems, and custom data structures.

Why We Use Iterator Pattern in C#?

We use the Iterator pattern in C# to:

• Traverse collections without exposing internal details
• Provide a standard way to iterate over objects
• Support multiple traversal strategies
• Simplify collection access logic
• Improve encapsulation
• Separate iteration logic from collection logic
• Enable foreach loop support
• Reduce duplicate traversal code

When Should We Use Iterator Pattern in C#?

The Iterator pattern should be used when:

• A collection needs sequential access
• Internal collection structure should remain hidden
• Multiple traversal methods are required
• Collections have complex internal structures
• You want standard iteration support
• Different collection types need a common traversal mechanism
• You want to support foreach iteration

Common Programming Problems Solved by Iterator Pattern

• Traversing custom collections
• Navigating tree structures
• Iterating graph nodes
• Reading streamed data
• Paging through records
• Processing large datasets lazily
• Supporting multiple traversal orders
• Hiding collection implementation details

Structure of Iterator Pattern in C#

Typical participants:

• Iterator Interface
• Concrete Iterator
• Aggregate Interface
• Concrete Aggregate
• Client

Basic workflow:

• Client requests iterator from collection
• Iterator tracks current position
• Client accesses elements sequentially
• Iterator moves to next element until traversal ends

Iterator Pattern Examples in C#

Example 1: Custom Number Collection Iterator

A custom collection should support sequential iteration using foreach.

using System;
using System.Collections;
using System.Collections.Generic;

public class NumberCollection : IEnumerable<int>
{
    private List<int> numbers = new List<int>();

    public void Add(int number)
    {
        numbers.Add(number);
    }

    public IEnumerator<int> GetEnumerator()
    {
        return numbers.GetEnumerator();
    }

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

public class Program
{
    public static void Main()
    {
        NumberCollection collection = new NumberCollection();

        collection.Add(10);
        collection.Add(20);
        collection.Add(30);

        foreach (int number in collection)
        {
            Console.WriteLine(number);
        }
    }
}

Example 2: Custom Iterator with Manual Traversal

A collection requires explicit iterator control.

using System;

public interface IIterator
{
    bool HasNext();
    string Next();
}

public class NameIterator : IIterator
{
    private string[] names;
    private int position = 0;

    public NameIterator(string[] names)
    {
        this.names = names;
    }

    public bool HasNext()
    {
        return position < names.Length;
    }

    public string Next()
    {
        return names[position++];
    }
}

public class NameCollection
{
    private string[] names = { "John", "Alice", "Bob" };

    public IIterator CreateIterator()
    {
        return new NameIterator(names);
    }
}

public class Program
{
    public static void Main()
    {
        NameCollection collection = new NameCollection();

        IIterator iterator = collection.CreateIterator();

        while (iterator.HasNext())
        {
            Console.WriteLine(iterator.Next());
        }
    }
}

Example 3: Tree Traversal Iterator

A tree structure should be traversed recursively.

using System;
using System.Collections.Generic;

public class TreeNode
{
    public string Value { get; set; }
    public List<TreeNode> Children { get; set; }

    public TreeNode(string value)
    {
        Value = value;
        Children = new List<TreeNode>();
    }

    public IEnumerable<TreeNode> Traverse()
    {
        yield return this;

        foreach (var child in Children)
        {
            foreach (var node in child.Traverse())
            {
                yield return node;
            }
        }
    }
}

public class Program
{
    public static void Main()
    {
        TreeNode root = new TreeNode("Root");

        root.Children.Add(new TreeNode("Child 1"));
        root.Children.Add(new TreeNode("Child 2"));

        foreach (var node in root.Traverse())
        {
            Console.WriteLine(node.Value);
        }
    }
}

Most Known Real-World Use Cases in C#

• foreach loops
• LINQ query execution
• Collection frameworks
• File streaming readers
• XML and JSON parsers
• Tree and graph traversal
• Database result iteration
• Pagination systems
• Lazy-loaded collections

Advantages of Iterator Pattern in C#

• Hides internal collection structure
• Supports standard traversal
• Simplifies client code
• Enables multiple traversal strategies
• Improves encapsulation
• Supports lazy evaluation
• Reduces duplicated iteration logic
• Works naturally with foreach

Disadvantages (Weak Points) of Iterator Pattern in C#

• Adds extra classes/interfaces
• Can increase complexity for small collections
• Traversal state management may become difficult
• Multiple iterators may consume extra memory
• Recursive iterators may impact performance
• Concurrent modifications can cause issues

Comparison with Similar Patterns

Pattern Main Purpose Traversal Support State Management Typical Usage Main Difference from Iterator
Iterator Sequential collection traversal Yes Inside iterator Collections, LINQ, foreach Focuses specifically on traversal abstraction
Composite Represent tree structures Optional In tree nodes UI trees, file systems Focuses on hierarchical object composition
Visitor Add operations to structures Usually combined Visitor object Compilers, syntax trees Adds operations rather than traversal abstraction
Enumerator Low-level iteration mechanism Yes Enumerator object .NET collections Enumerator is the .NET implementation detail of Iterator
Observer Notify subscribers No Observer list Events, messaging Focuses on event notification instead of traversal

Simplified UML-Style Structure

Component Responsibility
Client Uses iterator to access collection items
Iterator Defines traversal operations
ConcreteIterator Tracks current traversal position
Aggregate Creates iterator objects
ConcreteAggregate Stores collection data