如何修复这个lambda表达式

本文关键字:lambda 表达式 何修复 | 更新日期: 2023-09-27 18:07:45

根据多个用户选择的列进行排序:

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已被增加到比列表中最高索引大1的位置,并抛出错误。我知道我可以在每次排序之后执行ToList(),但这违背了目的,甚至不能保证对所有linq提供程序进行正确排序。我相信有一个简单的解决办法……有人能告诉我是什么吗?:)

如何修复这个lambda表达式

看起来您可能被变量x的闭包绊倒了。

该变量在循环的每次迭代中递增。最后一次加1,此时它比"sortFields"中的项数大1,条件语句的计算结果为False,并且for循环结束。

正如user2864740和Eric在他的文章中指出的:

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

因此,当调用ToList()时,链接的ThenBy语句保留变量x最终值,该值比最高索引大1。

将递增式赋值给循环中的中间变量。当您调用ToList()时,x的最终值将无关紧要。

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

同样来自Eric的文章,这个问题(希望)很快就会得到纠正,尽管显然只在foreach循环中,而不是for循环中:

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

Try

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