如何修复这个lambda表达式?

时间:2014-06-10 04:27:34

标签: c# .net linq lambda

我有这个函数可以按多个用户选择的列进行排序:

public override void Sort(SortFields sortFields)
{
    if (sortFields == null || sortFields.Count() == 0) return;

    var res = FilteredItems.OrderBy(o => o[sortFields[0].Name], sortFields[0].Ascending ? comparer : comparerDesc);

    for (int x = 1; x < sortFields.Count(); x++)
        res = res.ThenBy(o => o[sortFields[x].Name], sortFields[x].Ascending ? comparer : comparerDesc);

    FilteredItems = new BindingList<T>(res.ToList());

    if (ListChanged != null)
        ListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, null));
}

当然,问题在于,当调用res.ToList()时,x已增加到大于列表中最高索引的值,并且它会引发错误。我知道我可以继续在每次排序之后执行ToList()但是这会破坏目的,甚至不能保证与所有linq提供程序正确排序。我确信这有一个简单的解决方案......任何人都想告诉我它是什么? :)

2 个答案:

答案 0 :(得分:4)

看起来您可能会因变量x closure被绊倒。

单个变量在循环的每次迭代中递增。它最后一次递增,此时它的值大于&#34; sortFields&#34;中的项目数,您的条件语句的计算结果为False,而您的{{ 1}}循环结束。

正如user2864740指出的那样,埃里克在他的文章中指出:

  

闭包关闭变量,而不是超过值。

因此,当您再调用for时,您的链式ToList()语句会保留变量ThenBy最终值,该值比最高索引大1

相反,将增量器分配给循环内的中间变量。当您致电x时,ToList()的最终价值无关紧要。

x

同样来自Eric的文章,这(希望)很快就会得到纠正,但显然仅在for (int x = 1; x < sortFields.Count(); x++) { int y = x; res = res.ThenBy(o => o[sortFields[y].Name], sortFields[y].Ascending ? comparer : comparerDesc); } 循环中,而不是foreach循环:

  

在C#5中,foreach的循环变量将在逻辑上位于循环内部,因此闭包每次都会关闭变量的新副本。 &#34; for&#34;循环不会改变。

答案 1 :(得分:0)

尝试

var res = FilteredItems.OrderBy(o => o[sortFields[0].Name], sortFields[0].Ascending ? comparer : comparerDesc).ToList();