LINQ查询的结果是否保证总是按正确顺序返回?

7

问题:LINQ查询结果是否总是保证正确排序?

示例:

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; 

var lowNums = 
  from n in numbers 
  where n < 5 
  select n; 

现在,当我们遍历查询结果的记录时,它们是否按照输入数据 numbers 的顺序排列?

foreach (var x in lowNums) 
  { 
    Console.WriteLine(x); 
  } 

如果有人能在文档中提供关于排序的注释,那就太完美了。

使用 var lowNums = numbers.Where(x => x < 5).OrderBy(x => x); - Federico Berasategui
1
也许这可以帮助你:https://dev59.com/Ym025IYBdhLWcg3wNTEV。如果它是IEnumerable,它将保持原始顺序。 - thepirat000
2个回答

6

你有找到任何文件保证Linq-To-Objects的顺序保持不变吗? - Tim Schmelter
2
有趣的是,这些文档确实指出group by保留其顺序。 - Steven
1
@TimSchmelter 是的,我刚刚纠正了我的评论,指出它只是没有被提到。我同意微软可能永远不会改变它。然而,我仍然会编写我的代码,假设顺序不能保证。特别是因为LINQ to Objects是唯一像这样工作的。我宁愿不要把我的软件建立在一个方便的巧合上。 - evanmcdonnal
1
@evanmcdonnal:但如果输入序列已经排序,再次排序就是多余和低效的。因此,知道顺序不会改变很重要。Linq-To-Objects 与使用关系型数据库管理系统的其他提供程序无法比拟。 - Tim Schmelter
@TimSchmelter 我实际上在考虑第三方提供商和尚不存在的提供商,但是假设没有性能损失(我认为通常情况下都是这样),我会在排序之前执行我的LINQ查询。 - evanmcdonnal
显示剩余4条评论

0

我认为通过 LINQ 检索的元素顺序是有保留的,至少对于 LINQ to Object 是如此,对于 LINQ to SQL 或 Entity,它可能取决于表中记录的顺序。对于 LINQ to Object,我将尝试解释为什么它保留了顺序。

实际上,当执行 LINQ 查询时,IEnumerable 源会调用 GetEnumerator() 开始循环,并使用 while 循环 获取下一个元素。这就是在 IEnumerable 源上工作的 foreach 的原理。我们都知道,在列表/集合中,foreach 会保留元素的顺序。更深入地研究 MoveNext(),我认为它只有一些 Position 来保存当前的 Index,而 MoveNext() 只是增加了 Positionyield 相应的元素(在新位置)。这就是为什么它应该保留顺序,所有改变原始顺序的代码都是多余的,或者通过显式调用 OrderByOrderByDescending 来实现

如果您认为这个

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获得的IEnumeratorMoveNext()如何实现。然而,可以确定的是LINQ结果中元素的顺序将与foreach循环处理元素的顺序相同


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接