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
Post a Comment