如何修复这个lambda表达式?

时间:2021-03-15 19:05:40

I have this function for sorting by multiple user selected columns:

我有这个功能,可以按多个用户选择的列进行排序:

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));
}

The problem, of course, is that when res.ToList() is called x has been incremented to one greater than the highest index in the list and it throws an error. I know I could go ahead and do a ToList() after each sort but that defeats the purpose and isn't even guaranteed to sort correctly with all linq providers. I'm sure there's a simple solution to this... anyone want to tell me what it is? :)

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

2 个解决方案

#1


4  

It looks like you may be getting tripped up by a closure over the variable x.

看起来你可能会因变量x的闭包而被绊倒。

That single variable is incremented on every iteration of the loop. It's incremented one last time, at which point it's 1 greater than the number of items in "sortFields", your conditional statement evaluates to False, and your for loop ends.

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

As user2864740 pointed out, and Eric states in his article:

正如user2864740指出的那样,Eric在他的文章中说:

Closures close over variables, not over values.

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

So when you then call ToList(), your chained ThenBy statements retain the final value of the variable x, which was 1 greater than the highest index.

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

Instead, assign the incrementer to an intermediary variable inside the loop. When you call ToList(), the final value of x won't matter.

而是将增量器分配给循环内的中间变量。当您调用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);
}

Also from Eric's article, this is (hopefully) being corrected soon, though only in foreach loops apparently, not for loops:

同样来自Eric的文章,这是(希望)很快就会被纠正,虽然只是在foreach循环中显然,而不是循环:

In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The "for" loop will not be changed.

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

#2


0  

Try

尝试

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

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

#1


4  

It looks like you may be getting tripped up by a closure over the variable x.

看起来你可能会因变量x的闭包而被绊倒。

That single variable is incremented on every iteration of the loop. It's incremented one last time, at which point it's 1 greater than the number of items in "sortFields", your conditional statement evaluates to False, and your for loop ends.

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

As user2864740 pointed out, and Eric states in his article:

正如user2864740指出的那样,Eric在他的文章中说:

Closures close over variables, not over values.

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

So when you then call ToList(), your chained ThenBy statements retain the final value of the variable x, which was 1 greater than the highest index.

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

Instead, assign the incrementer to an intermediary variable inside the loop. When you call ToList(), the final value of x won't matter.

而是将增量器分配给循环内的中间变量。当您调用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);
}

Also from Eric's article, this is (hopefully) being corrected soon, though only in foreach loops apparently, not for loops:

同样来自Eric的文章,这是(希望)很快就会被纠正,虽然只是在foreach循环中显然,而不是循环:

In C# 5, the loop variable of a foreach will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time. The "for" loop will not be changed.

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

#2


0  

Try

尝试

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

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