For-Loop and LINQ's deferred execution don't play well together

前端 未结 2 1068
执念已碎
执念已碎 2021-01-18 20:51

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 dynamically by each \"colum

相关标签:
2条回答
  • 2021-01-18 20:59

    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.

    0 讨论(0)
  • 2021-01-18 21:21

    This is probably happening because the value of i is not closed within the loop - when the loop exits, i will have a value of 2 and then t[i] will be evaluated because of deferred execution.

    One solution is to create a closing variable within the loop:

    int minDim = someValues.Min(t => t.GetLength(0));  // 2
    IOrderedEnumerable<string[]> orderedValues = someValues.OrderBy(t => t[0]);
    for (int i = 1; i < minDim; i++)
    {
        var x = i;
        orderedValues = orderedValues.ThenBy(t => t[x]);
    }
    someValues = orderedValues.ToList(); 
    
    0 讨论(0)
提交回复
热议问题