C# Linq OrderBy()与List.Sort()的速度

C# Linq OrderBy()与List.Sort()的速度,c#,performance,linq,sorting,ienumerable,C#,Performance,Linq,Sorting,Ienumerable,下面是随机整数的枚举: var r = new Random(); var e = Enumerable.Repeat(1, 10_000_000).Select( _ => r.Next()); 您认为哪个版本更快: var result = e.OrderBy(x => x).Last(); //materialize the IEnumerable 或 我希望第一个示例中的.OrderBy(x=>x).Last()是 优化为只对列表的一小部分进行排序,或只对列表进行O(n)

下面是随机整数的枚举:

var r = new Random();
var e = Enumerable.Repeat(1, 10_000_000).Select( _ => r.Next());
您认为哪个版本更快:

var result = e.OrderBy(x => x).Last(); //materialize the IEnumerable

我希望第一个示例中的
.OrderBy(x=>x).Last()
是 优化为只对列表的一小部分进行排序,或只对列表进行O(n)步

扰流板: 不是

但是,这两个版本的性能至少应该是可比的,对吗?我的意思是:

在第一个示例中,
OrderBy()
分配一个临时数组并将其排序到位。
在第二个示例中,我显式地分配了一个列表,并将其放置到位

实际结果表明,
OrderBy()
示例的速度慢了4-5倍!(5-6秒与1.2-1.3秒)

有人能解释一下原因吗?

.OrderBy(x=>x)
案例为每个元素执行其
x=>x
标识lambda。
两者之间的区别:

var result2 = e.Last();


是可测量的,但很小:在第二种情况下多30-50毫秒。因此,这并不能解释巨大的差距。

似乎
列表
在与
比较器比较类型时使用了一个默认值。默认值为
或无
IComparer
OrderBy
总是对任何类型和
IComparer
进行通用排序

如果将
结果替换为
MyInt
类型的对象,如下所示:

public class MyInt : IComparable {
    public int value;
    public MyInt(int newv) => value = newv;

    public int CompareTo(object obj) {
        if (obj is MyInt m2) {
            return value.CompareTo(m2.value);
        }
        else if (obj is int i2) {
            return value.CompareTo(i2);
        }
        else {
            throw new Exception($"can't compare MyInt to {obj.GetType()}");
        }
    }
}

var e = Enumerable.Repeat(1, 10_000_000).Select(_ => new MyInt(r.Next()));
然后,
OrderBy
将比
List.Sort
方法快2倍

注意,如果你使用<代码>比较器。创建< <代码> >创建< <代码>比较器>代码> <代码> MyInt <代码> >代码>列表。排序< /代码>与<>代码> OrderBy < /代码>:

l.Sort(Comparer<MyInt>.Create((m1,m2) => m1.value.CompareTo(m2.value)));
l.Sort(Comparer.Create((m1,m2)=>m1.value.CompareTo(m2.value));

这就是为什么我希望有
Min()
Max()
版本返回对象而不是值。这样可以避免对整个项目集进行排序,以获得具有最高或最低值的对象。@itsme86您的意思是什么?您始终可以执行
IEnumerable thingsList=。。。;MyThing pubBum=thingsList.Max(thing=>thing.beersbeforeforcollasing)
返回
int
假设
beersbeforcollasing
int
。我猜它也可能是一个花车。哦,哇,你说得对!很抱歉,我敢打赌(而且是赔钱的!)LinqToObject没有做任何聪明的融合优化
OrderBy().Last()
OrderBy()
后跟
Last()
,而不是比单个操作更快的操作。您基本上是在问为什么就地排序操作
List.sort
(使用)比
Enumerable.OrderBy
(使用快速排序,受通过键选择器lambda进行比较的要求限制)快。如果你想弄清真相,我可能会告诉你。
public class MyInt : IComparable {
    public int value;
    public MyInt(int newv) => value = newv;

    public int CompareTo(object obj) {
        if (obj is MyInt m2) {
            return value.CompareTo(m2.value);
        }
        else if (obj is int i2) {
            return value.CompareTo(i2);
        }
        else {
            throw new Exception($"can't compare MyInt to {obj.GetType()}");
        }
    }
}

var e = Enumerable.Repeat(1, 10_000_000).Select(_ => new MyInt(r.Next()));
l.Sort(Comparer<MyInt>.Create((m1,m2) => m1.value.CompareTo(m2.value)));