LINQ to Objects是否保持其顺序?

18

我有一个 List<Person>,我想将它们转换为一个List<string>,以便进行简单处理。转换步骤如下:

List<Person> persons = GetPersonsBySeatOrder();
List<string> seatNames = persons.Select(x => x.Name).ToList();

Console.WriteLine("First in line: {0}", seatNames[0]);

.Select() 语句在 LINQ to Objects 对象上是否保证不改变列表成员的顺序?假设没有添加显式的去重/分组/排序。

此外,如果首先使用任意的 .Where() 子句,它是否仍然保证保留相对顺序,或者有时会使用非迭代过滤?


如Fermin在上面评论中所述,这本质上是一个重复的问题。我在选择正确的关键词来搜索stackoverflow上失败了。

Preserving order with LINQ


5
这里有关于 Linq 查询和排序的好细节:https://dev59.com/5nVC5IYBdhLWcg3wtzkQ - Fermin
3个回答

2

这取决于底层集合类型而不是其他任何因素。你可能会从一个HashSet中获得不一致的排序,但List是安全的。即使你想要的排序是隐含提供的,如果需要的话最好定义显式排序。从你的方法名称来看,似乎你正在这样做。


1

在当前的.Net实现中,它使用这样的代码。但是不能保证这种实现将来会存在。

private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
  int index = -1;
  foreach (TSource source1 in source)
  {
    checked { ++index; }
    yield return selector(source1, index);
  }
}

2
我怀疑像 .Select() 这样被广泛使用的内部实现,不会被更改为以不同顺序返回对象。 - Fermin
1
数据库行没有保证的顺序。列表有。这应该绝对取决于基础集合类型(即基础集合类型的枚举器),并且应该保留列表顺序,有保证。选择将使用列表类型的枚举器,并且目前它保留顺序,有保证。 - Triynko
@Fermin,实际上在.NET和.NET Core之间的Join中确实发生了变化,但一旦发现就进行了更正。 - Cory Nelson

1
是的,Linq的Select函数保证按照传入的枚举顺序返回所有结果。像大多数Linq函数一样,它的功能已经完全确定。除了错误处理之外,这几乎可以视为Select的代码:
IEnumerable<Y> Select<X, Y>(this IEnumerable<X> input, Func<X, Y> transform)
{
    foreach (var x in input)
        yield return transform(x);
}

但正如Samantha Branham所指出的那样,底层集合可能没有固有的顺序。我见过在读取时重新排列自己的哈希表。


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