(C# Language) LINQ - IEnumerable, yield and Enumerator

This tutorial introduces you to the IEnumerable interface and its practical significance. After that we discuss the internal workings of this interface. We demonstrate how the yield keyword can be used to return an IEnumerable from a function. The tutorial concludes with a C# program to efficiently print a fibonacci series by using the yield keyword and statement.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

Table of Contents (top down ↓)

What is IEnumerable

IEnumerable interface is implemented by collections and arrays. It signals the ability to provide its items one by one like a stream; it supports a simple iteration by using a loop.


// get IEnumerable 
var ie = new int[] { 3, 5, 6 };

// get IEnumerator 
var iterator = ie.GetEnumerator();

while (iterator.MoveNext())
{
  Console.WriteLine($"{iterator.Current}");
}

/* output
3
5
6
*/


IEnumerable interface implements a method called GetEnumerator that provides an enumerator for the collection. This enumerator is another interface that provides the next element through the MoveNext method that returns false when it reaches past the end of the collection. It provides the current element through a property called Current.

A while keeps moving the iterator. Each item is available in the Current property and displayed using console writeline.

This code is a roundabout way of looping through the elements. But things are not that difficult in real practice. A for-each loop simplifies this iteration. The code can be simplified a lot as you are seeing here.


// a foreach loop is simpler 
// does the same thing 

var ie = new int[] { 3, 5, 6 };

foreach(var item in ie)
{
  Console.WriteLine($"{item}");
}

A for-each loop directly provides the item. You must already be familiar with this code. It hides a lot of code behind the scenes.

Video Explanation (see it happen!)

Please watch the following youtube video:

What is yield keyword?

An IEnumerable can be obtained from a function by using the yield keyword.

Suppose we have to provide integers from a function as shown here. This function returns an IEnumerable. But there are multiple yield statements each of which returns an int. This code might be confusing at first. But it is a C# feature that successively executes each yield return statement after each call to the getNumbers function. Notice that all numbers are not returned in one step. Multiple calls are needed to stream the numbers. This technique makes optimal use of both the processor and memory.

Let me explain how the steps take place. Execution proceeds till the first yield statement. The data is returned to the caller and execution is suspended. The execution resumes at the next yield statement when the next iteration takes place. This sequence of suspend-resume siphons out the numbers step-by-step. It optimizes the use of processor and memory.


// program.cs file 

IEnumerable<int> getNumbers()
{
  yield return 0;
  yield return 3;
  yield return -9;
  yield return 2;
  yield return 45;
}

// foreach to iterate over IEnumerable 
foreach (var n in getNumbers())
{
  Console.WriteLine(n);
}

A for-each loop has been used to obtain the numbers one by one. The series is, step-by-step, printed on the console.

Printing a Fibonacci Series

The yield statement can be used to write a very readable program for printing a fibonacci series.

Let us write a program to print the first 20 fibonacci numbers.


// program.cs file 
// prints a fibonacci series 

IEnumerable<int> getNumbers()
{
  int first = -1;

  int second = 1;

  for (int i = 0; i < 20; i++)
  {
    int sum = first + second;

    first = second;

    second = sum;

    yield return sum;
  }
}

// print the sequence 
foreach (var n in getNumbers())
{
  Console.WriteLine(n);
}

We have to write a function that returns an IEnumerable of int numbers.

We have created two variables, first and second to hold consequetive numbers.

A for-loop is required to return 20 numbers one-by-one.

The sum of first and second is done. After that the values of first and second are shifted as per the fibonacci series.

Finally, the yield return statement returns the fibonacci number.

Notice that the yield keyword makes the whole process readable, intuitive and memory efficient at the same time.

A for-each loop makes the iteration calls and prints all the 20 numbers one-by-one. Thankyou!


This Blog Post/Article "(C# Language) LINQ - IEnumerable, yield and Enumerator" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.