我认为通过 LINQ
检索的元素顺序是有保留的,至少对于 LINQ to Object
是如此,对于 LINQ to SQL 或 Entity
,它可能取决于表中记录的顺序。对于 LINQ to Object
,我将尝试解释为什么它保留了顺序。
实际上,当执行
LINQ
查询时,
IEnumerable
源会调用
GetEnumerator()
开始循环,并使用
while 循环
获取下一个元素。这就是在
IEnumerable
源上工作的
foreach
的原理。我们都知道,在列表/集合中,
foreach
会保留元素的顺序。更深入地研究
MoveNext()
,我认为它只有一些
Position
来保存当前的
Index
,而
MoveNext()
只是增加了
Position
并
yield
相应的元素(在新位置)。这就是为什么它应该保留顺序,
所有改变原始顺序的代码都是多余的,或者通过显式调用 OrderBy
或 OrderByDescending
来实现。
如果您认为这个
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
foreach(var i in numbers)
if(i < 5) Console.Write(i + " ");
输出4 1 3 2 0
,你应该思考一下
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
IEnumerator ie = numbers.GetEnumerator();
while(ie.MoveNext()){
if((int)ie.Current < 5) Console.Write(ie.Current + " ");
}
还会打印出4 1 3 2 0
。因此,这个LINQ
查询。
var lowNums = from n in numbers
where n < 5
select n;
foreach (var i in lowNums) {
Console.Write(i + " ");
}
还应该打印出4 1 3 2 0
。
结论:LINQ
中元素的顺序取决于从IEnumerable
获得的IEnumerator
的MoveNext()
如何实现。然而,可以确定的是LINQ
结果中元素的顺序将与foreach
循环处理元素的顺序相同。
var lowNums = numbers.Where(x => x < 5).OrderBy(x => x);
。 - Federico Berasategui