这是这个优秀问题C# Sort and OrderBy comparison的后续。我将使用相同的示例:
List<Person> persons = new List<Person>();
persons.Add(new Person("P005", "Janson"));
persons.Add(new Person("P002", "Aravind"));
persons.Add(new Person("P007", "Kazhal"));
争论的方法是:
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
//and
persons.OrderBy(n => n.Name);
首先让我说,我知道没有任何显着的性能差异需要担心。但我很想知道为什么它OrderBy
的表现比Sort
. 我正在使用@phoog 在原始问题中发布的答案。
private void button1_Click(object sender, EventArgs e)
{
IEnumerable<Person> people;
BenchMark(persons => persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)));
BenchMark(persons => people = persons.OrderBy(n => n.Name));
}
private static Random randomSeed = new Random();
public static string RandomString(int size, bool lowerCase)
{
var sb = new StringBuilder(size);
int start = (lowerCase) ? 97 : 65;
for (int i = 0; i < size; i++)
{
sb.Append((char)(26 * randomSeed.NextDouble() + start));
}
return sb.ToString();
}
private static void BenchMark(Action<List<Person>> action)
{
List<Person> persons = new List<Person>();
for (int i = 0; i < 10000; i++)
{
persons.Add(new Person("P" + i.ToString(), RandomString(5, true)));
}
List<Person> unsortedPersons = new List<Person>(persons);
Stopwatch watch = new Stopwatch();
for (int i = 0; i < 100; i++)
{
watch.Start();
action(persons);
watch.Stop();
persons.Clear();
persons.AddRange(unsortedPersons);
}
MessageBox.Show(watch.Elapsed.TotalMilliseconds.ToString());
}
结果:
Sort() => 3500 ~ 5000 ms
OrderBy() => 0.2 ~ 1.5 ms
尽管即使我最初测试的列表较小,差异也很大,但随着集合的大小增加,它变得越来越明显。可能是我遗漏了一些理解 .NET 集合的关键,但我的想法是,既然Sort
作用于现有的.NET 集合,与作用于相同集合的(在我们的例子中)List<T>
相比,OrderBy
它在处理中的开销(如果有的话)应该更小,但是必须返回另一个集合。但仍然表现得要好得多。与类型相比可能会有一定的开销,但无论如何都会对现有列表起作用!此外,我很高兴看到一种方法比现有的 .NET 方法运行得更快。List<T>
persons
IOrderedEnumerable<T>
OrderBy
List<T>
IEnumerable<T>
Sort
Linq
原始问题中的所有答案都Sort
与OrderBy.ToList
我认为会有一些开销进行比较,因此或多或少地表现相同。
实施差异可能是什么?
编辑:好的,我学到了一些新东西。以下是我确认延期执行的方式。
private void button1_Click(object sender, EventArgs e)
{
BenchMark(persons =>
{
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
foreach (var item in persons)
{
break;
}
});
BenchMark(persons =>
{
IEnumerable<Person> people = persons.OrderBy(n => n.Name);
foreach (var item in people)
{
break;
}
});
}
Sort
运行时间为 4000 - 5000 毫秒,而OrderBy
运行时间略高于 5000 毫秒。所以确实我的结论是错误的。一旦我开始列举这些收藏品,它们的表现就相当了。我更喜欢anyday的语法OrderBy
:)
编辑 2:我刚刚发现这与此完全相同。但是这里有一个更有趣的问题,一般来说是关于延迟执行,虽然不是完全关于排序。