Iterator pattern in C#

 Hello, C# lovers! 😍

Today I want to talk about one of the most useful and elegant design patterns in C#: the Iterator pattern. 🙌

The Iterator pattern allows you to access the elements of a collection in a sequential manner without exposing its internal representation. 🤫

This way, you can abstract away the details of how the collection is stored and manipulated, and focus on what you want to do with the elements. 😎

The Iterator pattern is very common in C#, as it is used by the foreach loop and LINQ queries. 💯

Let’s see how it works with a simple example. Suppose you have a collection of stocks that you want to iterate over. You can define an interface for an iterator that provides methods to get the current element and move to the next one:


// The iterator interface
public interface IIterator<T>
{
    // Returns the current element
    T Current { get; }

    // Moves to the next element and returns true if successful
    bool MoveNext();
}


Then, you can define an interface for a collection that provides a method to create an iterator:


// The collection interface
public interface ICollection<T>
{
    // Returns an iterator for the collection
    IIterator<T> CreateIterator();
}


Now, you can implement these interfaces for your stock collection and iterator classes:


// A class that represents a stock
public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

// A class that represents a stock collection
public class StockCollection : ICollection<Stock>
{
    // An list of stocks as the internal representation
    private readonly List<Stock> _stocks = new List<Stock>();
// A method to add a stock to the collection public void Add(Stock stock)
{ _stocks.Add(stock);
} // A method to create an iterator for the collection public IIterator<Stock> CreateIterator() { return new StockIterator(this); } // A nested class that implements the iterator interface private class StockIterator : IIterator<Stock> { // A reference to the outer collection private StockCollection collection; // An index to keep track of the current position private int index = -1; // A constructor that takes the collection as a parameter public StockIterator(StockCollection collection) { this.collection = collection; } // A property that returns the current element public Stock Current { get { // Check if the index is valid if (index < 0 || index >= collection.stocks.Count) { throw new InvalidOperationException(); } // Return the stock at the current index return collection.stocks[index]; } } // A method that moves to the next element and returns true if successful public bool MoveNext() { // Increment the index and check if it is within bounds index++; return index < collection.stocks.Count; } } }


With this implementation, you can use your stock collection and iterator like this:


// Create a stock collection
StockCollection stockCollection = new StockCollection();

// Add an array of stocks
stockCollection.Add(new Stock { Symbol = "MSFT", Price = 300.25m });
stockCollection.Add(new Stock { Symbol = "AAPL", Price = 150.50m });
stockCollection.Add(new Stock { Symbol = "AMZN", Price = 3500.00m }); // Create an iterator for the collection IIterator<Stock> iterator = stockCollection.CreateIterator(); // Iterate over the stocks using the iterator while (iterator.MoveNext()) { // Get the current stock and print its details Stock stock = iterator.Current; Console.WriteLine($"{stock.Symbol}: {stock.Price}"); }


The output of this code is:


MSFT: 300.25
AAPL: 150.50
AMZN: 3500.00


As you can see, the iterator pattern makes it easy to iterate over any kind of collection without knowing how it is implemented internally. 🙌

You can also use different kinds of iterators for different purposes, such as filtering, sorting, or reversing the order of elements. 🚀

The iterator pattern is so useful that C# provides a standard way to implement it using IEnumerable and IEnumerator interfaces. These interfaces are similar to our custom ones, but they also support generics and IDisposable. 🌟

You can also use yield return statements to create iterators in a more concise and elegant way. 😍

For more information on how to use these features, check out these links:

That’s all for today, folks! I hope you enjoyed this article and learned something new about the iterator pattern in C#. 😊

If you have any questions or feedback, feel free to leave a comment below. 👇

And don’t forget to subscribe to my blog for more awesome C# content! 🔥

You can find the code examples here: source code

Happy coding! 😄

Comments

Popular posts from this blog

Which GOF patterns are good for C#?

Angular on a regular SharePoint page (part 2)

Chain of Responsibility pattern in C#