loading...

Bug Report #2 - Lazy Select In C#

horia141 profile image Horia Coman Originally published at horia141.com on ・2 min read

Bug Report (2 Part Series)

1) Bug Report #1 - GETUTCDATE() In Longer Queries 2) Bug Report #2 - Lazy Select In C#

This is the second in a series of articles about bugs I encounter while working. The first one was about GETUTCDATE() and how it complicates things in longer queries.

Today’s bug is about LINQ and the lazy IEnumerables it produces. A one-off script on which I spent way too much time worked something like this:

IEnumerable<Item> items = RawItems().Select(i => i.Transform());
foreach (var item in items)
    item.name = $"{item.name} #Modified";
UpdateItems(items);

Granted, not the most elegant code. But I thought it was enough to do it’s job. Turns out there’s a simple yet subtle bug occurring. Turns out that Select is quite lazy, so items is more like a promise that if you’re iterating it you’ll get the result of Transform() applied to each element from RawItems. But every time the iterator is used, that computation gets redone.

So the foreach loop actually modified each resulting element from one invocation of the iterator, but all that data was thrown away. When UpdateItems used items it obtained a new version of the derived data, without any of the modifications.

The solution is simple. Either include the modification as part of the Select and alongside Transform. Or make items non-lazy, by turning it into an List or Array, which is what I ended up doing for simplicity’s sake in my actual setup. So the code was now just:

IEnumerable<Item> items = RawItems().Select(i => i.Transform()).ToList();
foreach (var item in items)
    item.name = $"{item.name} #Modified";
UpdateItems(items);

Since the foreach loop and UpdateItems now referenced a list, instead of the iterator over something, the desired behaviour was achieved.

Bug Report (2 Part Series)

1) Bug Report #1 - GETUTCDATE() In Longer Queries 2) Bug Report #2 - Lazy Select In C#

Posted on by:

horia141 profile

Horia Coman

@horia141

Leading the Bolt teams in Bucharest. We're working on cool products like food delivery, and interesting and challenging platforms like geo, A/B testing, user accounts and route tracking.

Discussion

markdown guide