CSharp/C# Tutorial - C# Iterators






A foreach statement is a consumer of an enumerator.

An iterator is a producer of an enumerator.

In this example, we use an iterator to return a sequence of Fibonacci numbers:

using System;
using System.Collections.Generic;

class Main {
    static void Main() {
        foreach (int fib in Fibs(6)){
           Console.Write (fib + " ");
        }
    }
    static IEnumerable<int> Fibs (int fibCount) {
        for (int i = 0, prevFib = 1, curFib = 1; i < fibCount; i++) {
            yield return prevFib;
            int newFib = prevFib+curFib;
            prevFib = curFib;
            curFib = newFib;
        }
    }
}

A yield return statement return the next element from this enumerator.





Iterator Semantics

An iterator is a method, property, or indexer that contains one or more yield statements.

An iterator must return one of the following four interfaces:

// Enumerable interfaces
System.Collections.IEnumerable
System.Collections.Generic.IEnumerable<T>

// Enumerator interfaces
System.Collections.IEnumerator
System.Collections.Generic.IEnumerator<T>

Multiple yield statements are permitted. For example:

class Test {
   static void Main() {
      foreach (string s in Foo())
         Console.WriteLine(s); // Prints "One","Two","Three"
   }
   static IEnumerable<string> Foo() {
      yield return "One";
      yield return "Two";
      yield return "Three";
   }
}




yield break

The yield break statement indicates that the iterator block should exit early, without returning more elements.

The following code shows how to use yield break:

static IEnumerable<string> Foo (bool breakEarly) {
   yield return "One";
   yield return "Two";
   if (breakEarly)
      yield break;

   yield return "Three";
}

A return statement is illegal in an iterator block, use yield break instead.

Composing Sequences

The following code shows how to output even Fibonacci numbers only:

using System;
using System.Collections.Generic;

class Main {
   static void Main() {
      foreach (int fib in EvenNumbersOnly (Fibs(6)))
          Console.WriteLine (fib);
   }
   static IEnumerable<int> Fibs (int fibCount) {
      for (int i = 0, prevFib = 1, curFib = 1; i < fibCount; i++) {
         yield return prevFib;
         int newFib = prevFib+curFib;
         prevFib = curFib;
         curFib = newFib;
      }
   }
   static IEnumerable<int> EvenNumbersOnly (IEnumerable<int> sequence) {
      foreach (int x in sequence)
         if ((x % 2) == 0)
            yield return x;
   }
}