关于c#:为什么Array.Sort()与LINQ相比这么慢?

Why is Array.Sort() so slow compared to LINQ?

我制作了一个快速测试应用程序,将LINQ排序与自定义对象上的Array.Sort进行比较。
Array.Sort似乎非常慢!

我做了这样的自定义类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person : IComparable<Person>
{
    public int Age { get; set; }
    public string Name { get; set; }

    public int CompareTo(Person obj)
    {
        return this.Age.CompareTo(obj.Age);
    }

    public Person()
    { }

}

然后我在main()中设置了测试人员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
string name ="Mr. Tomek";

Random r = new Random();
int size = 10000000;

DateTime start, end;
Person[] people1 = new Person[size];
Person[] people2 = new Person[size];

for (int i = 0; i < size; i++)
{
     people1[i] = new Person();
     people1[i].Age = r.Next(0, 10000);
     people1[i].Name = name;

     people2[i] = new Person();
     people2[i].Age = people1[i].Age;
     people2[i].Name = people1[i].Name;
}

之后,我测量了Array.Sort和LINQ进行排序所需的时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
start = DateTime.Now;
var sort = from s in people2
           orderby s.Age
           select s;
end = DateTime.Now;
Console.WriteLine("LINQ:");
Console.WriteLine((end - start).TotalMilliseconds);

start = DateTime.Now;
Array.Sort(people1,((Person p1, Person p2)=>{return p1.CompareTo(p2);}));
end = DateTime.Now;

Console.WriteLine("IComparable:");
Console.WriteLine((end - start).TotalMilliseconds);

Console.ReadLine();

Linq时间:大约1或2毫秒

Array.Sort:超过16秒!

所有数组都已排序(LINQ产生新的集合,并使原始数组保持未排序状态),但是Array.Sort非常慢!怎么解释呢? (在调试和释放模式下,Array.Sort极其失败)

在使用Array.Sort排序时,我粘贴了带有lambda表达式的代码,但是无论是否带有它,它都是相同的。 (Class Person实现IComparable接口)


您的Linq查询甚至没有得到执行,因为您没有得到结果。这称为延迟执行。仅当您实际枚举结果时才执行查询。

使用类似var results = sort.ToArray()的命令执行查询,您将获得更准确的结果。


LINQ很懒。您的people2尚未实际排序,LINQ只是创建了一个临时的" promise对象",将对其进行排序。要使其真正实现,您必须通过Console.WriteLine排序结果来强制求值,将其转换为列表/数组或执行类似的其他操作。

查看更多:推迟执行。


Linq语句返回IEnumerable<T>或它的形式(或任何使用yield关键字的形式),仅在您对其进行迭代时执行。 Linq库中的大多数可用操作(不是全部)都是延迟的/延迟的。

您没有对其进行迭代,因此您实际上并未在执行排序。

您需要强制执行完整的迭代。将结果粘贴到列表中将完全迭代返回的可枚举:

1
2
3
var sort = (from s in people2
            orderby s.Age
            select s).ToList();

然后您才可以将苹果与苹果进行比较。

实际上,对于排序(orderby),仅选择第一项将导致完整的迭代,因为需要完全完成排序才能返回第一个结果:

1
2
3
4
5
var sort = from s in people2
           orderby s.Age
           select s;

var s = sort.First();

尝试更改此部分,然后再次进行测试。

1
2
3
4
5
    start = DateTime.Now;
    var sort = (from s in people2
               orderby s.Age
               select s).ToList();
    end = DateTime.Now;

这将评估LINQ表达式。