C# IEnumerable
last modified February 2, 2024
In this article we explain the C# IEnumerable interface.
IEnumerable
is a standard C# interface that enables iterating over
collections using the foreach loops. IEnumerable
uses
IEnumerator
internally. It is used to perform the iterations. It
controls moving from one element to the next in the list.
Objects implementing the IEnumerable
interface must define the
GetEnumerator
method, which returns the IEnumerator
.
The IEnumerator
implements the MoveNext
,
Reset
and Current
methods.
In addition, IEnumerable
also enables generators in C#, using
yield return
and yield break
statements and it is used
in combination with LINQ for data manipulation in collections.
Enabling foreach interations
IEnumerable
enables seamless interaction with foreach
keyword.
IEnumerable<int> range = Enumerable.Range(1, 6); List<string> words = ["sky", "cup", "beer"]; IEnumerable<char> chars = "an old falcon".AsEnumerable(); decimal[] vals = [1m, 2m, 3m]; DoIteration(range); DoIteration(words); DoIteration(chars); DoIteration(vals.AsEnumerable()); void DoIteration<T>(IEnumerable<T> vals) { foreach (var e in vals) { Console.Write($"{e} "); } Console.WriteLine(); }
In the program, we define a generic DoIteration
method that
iterates over a range of numbers, list of words, sequence of characters and an
array of chars.
IEnumerable<char> chars = "an old falcon".AsEnumerable();
A string is transformed into a sequence of chars with AsEnumerable
.
void DoIteration<T>(IEnumerable<T> vals)
The DoIteration
method takes a generic IEnumerable
as a parameter.
foreach (var e in vals) { Console.Write($"{e} "); }
We go through the passed parameters with foreach
.
$ dotnet run 1 2 3 4 5 6 sky cup beer a n o l d f a l c o n 1 2 3
IEnumerable and generators
The next program we creates an IEnumerable
of tuples from a
generator.
int n = 10; IEnumerable<string> res = FibSeq().TakeWhile(f => f.n <= n).Select(f => $"{f.fib}"); Console.WriteLine(string.Join(" ", res)); IEnumerable<(int n, int fib)> FibSeq() { yield return (0, 0); yield return (1, 1); var (x, y, n) = (1, 0, 0); while (x < int.MaxValue - y) { (x, y, n) = (x + y, x, n + 1); yield return (n, x); } }
In the example, we calculate the Fibonacci sequence.
IEnumerable<string> res = FibSeq().TakeWhile(f => f.n <= n).Select(f => $"{f.fib}");
We consume the Fibonacci sequence with the LINQ's TakeWhile
method.
Console.WriteLine(string.Join(" ", res));
The sequence of strings is joined.
IEnumerable<(int n, int fib)> FibSeq() { yield return (0, 0); yield return (1, 1); var (x, y, n) = (1, 0, 0); while (x < int.MaxValue - y) { (x, y, n) = (x + y, x, n + 1); yield return (n, x); } }
The FibSeq
method returns a sequence of tuple values. Each tuple
contains the n
value, up to which we generate the sequence and
the current Fibonacci value fib
.
yield return (0, 0); yield return (1, 1);
The first two tuples are returned with yield return
.
var (x, y, n) = (1, 0, 0); while (x < int.MaxValue - y) { (x, y, n) = (x + y, x, n + 1); yield return (n, x); }
The rest of the sequence is calculated with a while loop. The sequence goes
up to int.MaxValue
.
IEnumerable with a custom class
In the next example we create an enumerable custom class.
using System.Collections; Bag bag = new(); foreach (object e in bag) { Console.WriteLine(e); } class Bag : IEnumerable<object> { private readonly object[] data = [1, "falcon", 4.4m, new DateTime(2024, 01, 31)]; public IEnumerator<object> GetEnumerator() { foreach (var item in data) { yield return item; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
We define a Bag
class which can be traversed with a foreach
loop.
class Bag : IEnumerable<object> { private readonly object[] data = [1, "falcon", 4.4m, new DateTime(2024, 01, 31)]; public IEnumerator<object> GetEnumerator() { foreach (var item in data) { yield return item; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
The custom class implements the IEnumerable
interface. The
Bag
class defines the GetEnumerator
method. It
generates data from the data
array with yield return
.
$ dotnet run 1 falcon 4,4 31. 1. 2024 0:00:00
IEnumerable with query expressions
LINQ query expressions return IEnumerables
, which can be iterated
later with foreach
.
IEnumerable<int> vals = from value in Enumerable.Range(0, 5) select value; foreach (var e in vals) { Console.WriteLine(e); } List<string> words = [ "sky", "forest", "war", "buy", "crypto", "cup", "water", "cloud" ]; IEnumerable<string> res = from word in words where word.StartsWith('c') select word; Console.WriteLine(string.Join(',', res));
In the example, we iterate over two query expressions: a range of integers and a list of words.
$ dotnet run 0 1 2 3 4 crypto,cup,cloud
Source
IEnumerable<T> Interface - language reference
In this article we have covered the C# IEnumerable interface.
Author
List all C# tutorials.