これは、この優れた質問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
、既存のに作用するため、同じものに作用するもの(この場合は)List<T>
と比較して、処理のオーバーヘッドが (もしあれば) 少ないはずですが、別のコレクションを返す必要があります。しかし、それでもはるかに優れたパフォーマンスを発揮します。タイプに比べてオーバーヘッドがあるかもしれませんが、とにかく既存のリストに作用します! さらに、あるメソッドが既存の .NET メソッドよりも高速に動作するのを見るのはちょっと面白くありません。OrderBy
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 ミリ秒で実行され、5000 ミリ秒をOrderBy
わずかに上回って実行されました。だから確かに私の結論は間違っていました。コレクションの列挙を開始すると、どちらも同等の条件で実行されました。OrderBy
私はanydayの構文を好みます:)
編集 2:これはthis oneの正確な複製であることがわかりました。しかし、順序付けについてではなく、一般的な遅延実行に関するより興味深い質問があります。