Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OrderBy / ThenBy looping - nested Lists in C#

Tags:

c#

linq

I have a nested list,

List<List<String>> intable;

where I would like to sort all the columns. The problem is that the number of columns depends on user input.

Sorting the list like this works fine (assuming 4 columns for this example)

var tmp = intable.OrderBy(x => x[0]);
tmp = tmp.ThenBy(x => x[1]);
tmp = tmp.ThenBy(x => x[2]);
tmp = tmp.ThenBy(x => x[3]);
intable = tmp.ToList();

But, when I put it in a loop, like this:

var tmp = intable.OrderBy(x => x[0]);
for (int i = 1; i <= 3; i++)
{
        tmp = tmp.ThenBy(x => x[i]);
}
intable = tmp.ToList();

it no longer works correctly, and sorts only the fourth column.

like image 714
phil Avatar asked Jan 27 '12 18:01

phil


1 Answers

This is a case of access to a modified closure. Change the code to this and it will work:

var tmp = intable.OrderBy(x => x[0]);
for (int i = 1; i <= 3; i++) {
    var thisI = i;
    tmp = tmp.ThenBy(x => x[thisI]);
}
intable = tmp.ToList();

Eric Lippert has written a two-part article describing the problem. The reason it doesn't work as you expect to is - in short - because LINQ is only using the last value of i when it is evaluated when you call ToList(). It's the same as if you had written:

var tmp = intable.OrderBy(x => x[0]);
tmp = tmp.ThenBy(x => x[3]);
tmp = tmp.ThenBy(x => x[3]);
tmp = tmp.ThenBy(x => x[3]);
intable = tmp.ToList();
like image 111
Yuck Avatar answered Sep 18 '22 19:09

Yuck