Photo by Lisa P. on Unsplash

IEnumerable considered harmful

Goran Siska
2 min readApr 15, 2019

--

A few years ago I prepared a lecture on potential pitfalls when using IEnumerable. The lecture was designed to highlight the most common mistakes I’ve come across in production code. …

You can find the complete solution containing full code examples I’ve used in the lecture on GitHub.

I’ve classified the most common mistakes into individual chapters containing short explanations and demonstrations of the problems they might cause.

The first part of the lecture was intended to list the common misconceptions regarding IEnumerable interface. I made a case for calling it IGeneratable as that what the interface is describing. Many developers wrongly assume that IEnumerators are things that iterate over materialized collections and rarely consider they might be generators, creating new values per request.

Late evaluation

The first example of this misconception is the well known closure issue which used to exist in C# when using foreach statement.

We start by creating a list of functions. Next we populate this list by iterating over a range of numbers from zero to ten. Finally we output the result of calling these functions.

Most developers expect (and rightly so), the program to output numbers from zero to nine. The unexpected result of this program was to list number nine - ten times.

To understand the issue, we need to explain what the foreach statement did before and does now. Prior to c#5 the foreach statement would expand to something like:

The problem here is the declaration of the current variable is outside our loop. And our function ()=>current will return the value of the variable at the time of execution and not the value of the variable when the delegate was created.

Such problems lead the C# design team to make (a rare) breaking change in C#5 and now the foreach statement expands to:

Now the current variable is created in every loop and every delegate closes over a different variable. Now the program lists numbers from zero to nine as expected.

You can test this in practice with the code example from GitHub. The project includes the old compiler executable and a batch script to run the program and list the unexpected output.

Next time, we’ll take a look at bad coding patterns (using IEnumerable) that may result in unwanted, multiple evaluation of expressions.

--

--