LINQ Select扩展方法使用后的项目顺序

10

可能是重复问题:
使用 LINQ 保留顺序

假设我有以下 Person 类,进一步用于声明一个 Person 数组:

public class Person
{
    public int Id { get;set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

var persons = new[] {
    new Person { Id = 1, Name = "John", Age = 40 },
    new Person { Id = 2, Name = "John", Age = 30 },
    new Person { Id = 3, Name = "John", Age = 35 },
};

我使用以下的LINQ Select扩展方法,从Person数组中提取Age

var ages = persons.Select(p => p.Age).ToArray;

LINQ是否保证派生数组中的项目顺序与源数组中的项目顺序匹配,使得ages数组按照以下顺序排列?
40
30
35
5个回答

12
LINQ to Objects运算符实际上不会更改其原始数据源——它们构建的序列实际上是由数据源支持的。唯一改变排序顺序的操作是OrderBy / OrderByDescending / ThenBy / ThenByDescending,即使这些操作对于相同顺序的元素也是稳定的。当然,许多操作将过滤掉一些元素,但返回的元素将按照相同的顺序排列。
来自Jon Skeet在此处的答案
每个返回IEnumerable的操作的详细信息在同一问题中进一步说明:https://dev59.com/5nVC5IYBdhLWcg3wtzkQ#204777

6

Select() 保留顺序,这是肯定的。但当你使用 Distinct(), ToDictionary()ToLookup() 时要小心。


实际上,我在实际代码中使用了 Distinct()。我应该注意什么? - John Gathogo
它不保留原始顺序... 好吧,你不能确定它会被保留,那是不同的。 - Tommaso Belluzzo
@Zarathos Distinct实际上保留了原始顺序(至少在当前实现中),尽管这并不是文档的保证。 - Servy
1
好的,这就是我说的Servy:“你不能确定它会被保留”。 - Tommaso Belluzzo
我更喜欢直截了当的回答。 - Xcessity

2

这在一定程度上取决于您使用哪些对象和扩展方法。以下是一篇文章,列出了各种类型以及您可以期望的内容:保留LINQ中的顺序


1
当然可以!
物品将按照列表中的顺序进行处理。

0

Select(选择)通常接受一个可枚举对象,并按顺序对每个元素应用操作。

你可以这样想:

public static class Linq
{
    // We take in some data structure that supports enumeration and some function to apply to each element.
    public static IEnumerable<TResult> Select<T, TResult>(this IEnumerable<T> source, Func<T, TResult> operation)
    {
        foreach (var item in source)
        {
            // Here we simply return the next element
            // when the caller wants an item.
            yield return operation(item);
        }
    }
}

2
但问题是规格中是否有保证,或者他们可以在将来的实现中更改这种行为?在这种情况下是的,这与仅仅是当前实现的副作用不同。 - Servy

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