Introduction
Iterators in C# are a powerful feature allowing you to traverse collections such as arrays, lists, or any custom collection type. They provide an elegant way to access elements sequentially without exposing the underlying representation of the collection. This article explores the concept of iterators, their implementation, and practical use cases in C#.
What is an Iterator?
An iterator is a special object that facilitates the traversal of a collection one element at a time. In C#, iterators are implemented using the yield keyword in methods, properties, or accessors. When an iterator is called, it does not execute its code immediately. Instead, it returns an enumerator that allows you to step through the collection.
Implementing Iterators in C#
Using yield return
The yield return statement provides a simple way to implement an iterator. It allows you to return each element one at a time.
Here’s a basic example of an iterator implemented using yield return.
using System;
using System.Collections.Generic;
public class NumberCollection
{
private int[] numbers = { 1, 2, 3, 4, 5 };
public IEnumerator<int> GetEnumerator()
{
foreach (int number in numbers)
{
yield return number;
}
}
}
public class Program
{
public static void Main()
{
NumberCollection collection = new NumberCollection();
foreach (int number in collection)
{
Console.WriteLine(number);
}
}
}
Using yield break
The yield break the statement is used to end the iteration prematurely. It can be useful when certain conditions are met and further iteration is unnecessary.
using System;
using System.Collections.Generic;
public class EvenNumberCollection
{
private int[] numbers = { 1, 2, 3, 4, 5, 6 };
public IEnumerator<int> GetEnumerator()
{
foreach (int number in numbers)
{
if (number % 2 != 0)
{
yield break;
}
yield return number;
}
}
}
public class Program
{
public static void Main()
{
EvenNumberCollection collection = new EvenNumberCollection();
foreach (int number in collection)
{
Console.WriteLine(number);
}
}
}
Custom Iterators
Iterators can also be implemented for custom collection types. This is useful when you need to control the iteration logic explicitly.
using System;
using System.Collections;
using System.Collections.Generic;
public class CustomCollection<T> : IEnumerable<T>
{
private T[] items;
public CustomCollection(T[] items)
{
this.items = items;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < items.Length; i++)
{
yield return items[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Program
{
public static void Main()
{
CustomCollection<string> collection = new CustomCollection<string>(
new string[] { "Hello", "World", "C#", "Iterators" });
foreach (string item in collection)
{
Console.WriteLine(item);
}
}
}
Advantages of Using Iterators
- Simplicity: Iterators simplify the code required to traverse collections.
- Lazy Evaluation: Iterators provide elements only when they are needed, which can improve performance by avoiding unnecessary computation or memory allocation.
- Abstraction: They provide a way to access elements without exposing the underlying structure of the collection.
Conclusion
Iterators are a fundamental part of C# that provides a convenient way to traverse collections. By using the yield return and yield break statements, you can create powerful and flexible iteration mechanisms. Whether you're working with built-in collections or custom types, understanding and leveraging iterators can greatly enhance your ability to write clean and efficient code.