Introduction
Iterators are a new feature in C# 2.0. An iterator is a method, get accessor or operator that enables you to support foreach iteration in a class or struct without having to implement the entire IEnumerable interface. Instead, you provide just an iterator, which simply traverses the data structures in your class. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerable or IEnumerator interface.
Iterators Overview
- An iterator is a section of code that returns an ordered sequence of values of the same type.
- An iterator can be used as the body of a method, an operator, or a get accessor.
- The iterator code uses the yield return statement to return each element in turn. yield break ends the iteration.
- Multiple iterators can be implemented on a class. Each iterator must have a unique name just like any class member, and can be invoked by client code in a foreach statement as follows: foreach(int x in SampleClass.Iterator2){}
- The return type of an iterator must be IEnumerable or IEnumerator.
The yield keyword is used to specify the value, or values, returned. When the yield return statement is reached, the current location is stored. Execution is restarted from this location the next time the iterator is called. Iterators are especially useful with collection classes, providing an easy way to iterate non-trivial data structures such as binary trees.
Usage Scenario
Suppose we have a class named ProductCategory, and another class named Product. ProductCategory contains a collection of Product which you don't want to expose it as public. Instead, you will develop all methods to enable access of your Product collection. One of those will enable iteration through the Product collection. And this is what we will call Iterator.
Product Class
Product class is very simple as shown bellow:
class Product
{
private string _name;
public string ProductName
{
get { return _name; }
set { _name = value; }
}
public Product(string name)
{
_name = name;
}
public Product(){}
}
ProductCategory Class
ProductCategory class is also simple but it will contain the iterator method:
class ProductCategory
{
private List<Product> _products;
private string _name;
public string CategoryName
{
get { return _name; }
set { _name = value; }
}
public ProductCaltegory(string name) : this()
{
_name = name;
}
public ProductCaltegory()
{
_products = new List<Product>(5);
}
public void AddProduct(Product p)
{
_products.Add(p);
}
public IEnumerator GetEnumerator()
{
foreach (Product p in _products)
yield return p;
}
}
You must noticed the iterator method GetEnumerator, very simple, isn't it? The magic is in yield return statement. One thing you have to notice also, is the name of the iterator method! If you wish to use the ProductCategory instance with foreach statement as you'll see in the following example, you have to name the iterator method as GetEnumerator. Of course you can have multiple iterator methods, but GetEnumerator will be considered as the default method.
class Program
{
static void Main(string[] args)
{
Product p1 = new Product("Product A");
Product p2 = new Product("Product B");
Product p3 = new Product("Product C");
Product p4 = new Product("Product D");
ProductCaltegory category = new ProductCaltegory("Main Category");
category.AddProduct(p1);
category.AddProduct(p2);
category.AddProduct(p3);
category.AddProduct(p4);
foreach (Product p in category)
{
Console.WriteLine(p.ProductName);
}
}
}
Summary
The most common way to create an iterator is to implement the GetEnumerator method on the IEnumerable. The foreach statement invokes GetEnumerator and uses the returned enumerator to iterate through the values. GetEnumerator method is considered the default Iterator method.
References
C# Iterators on MSDN
yield (C# Reference) on MSDN
Please login to rate or to leave a comment.