Это продолжение этого замечательного вопроса С# Сортировка и сравнение OrderBy. Я буду использовать тот же пример:
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>
, он должен иметь меньшие накладные расходы (если каждый из них) при обработке по сравнению с OrderBy
, который действует на том же List<T>
(в нашем случае persons
), но нужно вернуть другую коллекцию IOrderedEnumerable<T>
. Но все же OrderBy
работает намного лучше. List<T>
может иметь определенные накладные расходы по сравнению с типом IEnumerable<T>
, но Sort
в любом случае действует на существующий список! Кроме того, я немного удивлен, увидев, что метод Linq
работает быстрее, чем существующий метод .NET.
Все ответы в исходном вопросе сравнивают 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 мс. Так что мой вывод был неправильным. Оба они выполнялись на равных условиях, как только я начал перечислять коллекции. Я предпочитаю синтаксис OrderBy
anyday:)
Изменить 2: Я только что нашел, что это точный дубликат этого. Но вот более интересный вопрос об отложенном исполнении в целом, хотя и не о заказе в целом.