The title suggests that i've already an idea what's going on, but i cannot explain it. I've tried to order a List<string[]>
dynamically by each "column", beginning with the first and ending with the minimum Length
of all arrays.
So in this sample it is 2
, because the last string[]
has only two elements:
List<string[]> someValues = new List<string[]>();
someValues.Add(new[] { "c", "3", "b" });
someValues.Add(new[] { "a", "1", "d" });
someValues.Add(new[] { "d", "4", "a" });
someValues.Add(new[] { "b", "2" });
Now i've tried to order all by the first and second column. I could do it statically in this way:
someValues = someValues
.OrderBy(t => t[0])
.ThenBy(t => t[1])
.ToList();
But if i don't know the number of "columns" i could use this loop(that's what I thought):
int minDim = someValues.Min(t => t.GetLength(0)); // 2
IOrderedEnumerable<string[]> orderedValues = someValues.OrderBy(t => t[0]);
for (int i = 1; i < minDim; i++)
{
orderedValues = orderedValues.ThenBy(t => t[i]);
}
someValues = orderedValues.ToList(); // IndexOutOfRangeException
But that doesn't work, it fails with an IndexOutOfRangeException
at the last line. The debugger tells me that i
is 2
at that time, so the for-loop condition seems to be ignored, i
is already == minDim
.
Why is that so? What is the correct way for this?
It's the same problem as lots of people had with foreach
loops pre C# 5.
orderedValues = orderedValues.ThenBy(t => t[i]);
The value of i
will not be evaluated until you call .ToList()
at which point it is 2 since that's the exit condition of the for loop.
You can introduce a new local variable inside the for-loop to fix it:
for (int i = 1; i < minDim; i++)
{
var tmp = i;
orderedValues = orderedValues.ThenBy(t => t[tmp]);
}
For more information you could take a look at Eric Lippert's blog post about Closing over the loop variable considered harmful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With