我有这个函数可以按多个用户选择的列进行排序:
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提供程序正确排序。我确信这有一个简单的解决方案......任何人都想告诉我它是什么? :)
答案 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();