In C#, advanced iterator patterns such as nested iterators, infinite sequences, and the combination of yield return
with regular return
statements enhance code flexibility and efficiency. These patterns enable the creation of complex data enumerations and allow developers to handle streams of data dynamically.
Iterators in C# allow you to iterate over sequences of data. They provide an efficient way to manage collection traversal and can enhance code readability and performance.
using System;using System.Collections;public class CustomIterator : IEnumerable{private int[] numbers = { 1, 2, 3, 4, 5 };public IEnumerator GetEnumerator() {for (int i = 0; i < numbers.Length; i++) {yield return numbers[i];}}}public class Program {public static void Main() {var iterator = new CustomIterator();foreach(var number in iterator) {Console.WriteLine(number);}}}
Understanding iterator methods is integral to managing collections in C#. An iterator method allows objects to be retrieved one at a time via yield return
, providing flexibility in both synchronous (IEnumerable<T>
) and asynchronous (IAsyncEnumerable<T>
) operations. This approach enhances performance by only generating items as needed.
using System.Collections.Generic;using System.Threading.Tasks;public class IteratorExample{// Synchronous iteratorpublic IEnumerable<int> GetNumbers(){for (int i = 0; i < 5; i++){yield return i;}}// Asynchronous iteratorpublic async IAsyncEnumerable<int> GetNumbersAsync(){for (int i = 0; i < 5; i++){await Task.Delay(100);yield return i;}}}
In C#, developers can create custom iterators by implementing the IEnumerable<T>
and IEnumerator<T>
interfaces manually. This allows for customized iteration logic, putting you in control of how elements in a collection are accessed.
// Example: Custom Iterator Implementation in C#using System;using System.Collections;using System.Collections.Generic;public class CustomCollection<T> : IEnumerable<T>{private readonly List<T> _items = new List<T>();public void Add(T item) => _items.Add(item);public IEnumerator<T> GetEnumerator() => new CustomEnumerator(_items);IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();private class CustomEnumerator : IEnumerator<T>{private readonly List<T> _items;private int _position = -1;public CustomEnumerator(List<T> items) => _items = items;public T Current => _items[_position];object IEnumerator.Current => Current;public bool MoveNext() => ++_position < _items.Count;public void Reset() => _position = -1;public void Dispose() { /* not needed */ }}}// Usagevar collection = new CustomCollection<int>();collection.Add(1);collection.Add(2);collection.Add(3);foreach (var item in collection){Console.WriteLine(item);}
C#
In C#, lazy evaluation in iterators delays the execution of a function until its result is needed. This optimizes performance and enhances memory efficiency by computing items only when required, avoiding unnecessary processing.
using System;using System.Collections.Generic;class Program{static IEnumerable<int> LazyNumbers(){Console.WriteLine("Generating numbers");yield return 1;yield return 2;yield return 3;}static void Main(){IEnumerable<int> numbers = LazyNumbers();Console.WriteLine("Number sequence created.");foreach (var num in numbers){Console.WriteLine(num);}}}/* Output:Number sequence created.Generating numbers123*/
Yield
KeywordThe yield
keyword in C# is used within an iterator block to define a sequence’s elements and control iteration. It simplifies code by allowing state retention between calls without requiring a temporary collection. This enhances memory efficiency and readability.
using System;using System.Collections.Generic;class Program{static void Main(){foreach (int number in GenerateNumbers()){Console.WriteLine(number);}}static IEnumerable<int> GenerateNumbers(){for (int i = 1; i <= 3; i++){yield return i;}}}