Различия OrderBy и ThenBy

Различия OrderBy и ThenBy

Последнее время все больше провожу сравнений различных операторов и конструкций языка. Сегодня пролистывая список методов сортировки в LINQ с удивлением обнаружил, что никогда не использовал метод ThenBy. О данном методе, а конкретно о сравнении его с OrderBy, сегодняшняя заметка.

Начнем наше обсуждение с простой задачи. Дан список пользователей на сайте, который нужно отсортировать.

public static IEnumerable<User> Users = new List<User>
{
	new User { Id = 1, FirstName = "John", LastName = "Smith" },
	new User { Id = 2, FirstName = "Jack", LastName = "Deniels" },
	new User { Id = 3, FirstName = "Petr", LastName = "Wilson" },
	new User { Id = 4, FirstName = "Vasiliy", LastName = "Petrov" },
	new User { Id = 5, FirstName = "Ivan", LastName = "Demidov" },
	new User { Id = 6, FirstName = "Jack", LastName = "Bond" },
	new User { Id = 7, FirstName = "Stephen", LastName = "Catz" }
};

Для того, чтобы отсортировать данный список по FirstName нужно выполнить небольшую команду.

var orderedUsers = users.OrderBy(c => c.FirstName);
foreach (var user in orderedUsers)
{
	Console.WriteLine($"{user.FirstName}, {user.LastName}");
}

А что если нам нужно отсортировать пользователя не только по имени, но и по фамилии? Попробуем воспользоваться следующим кодом. 

var orderedUsers = users.OrderBy(c => c.FirstName).OrderBy(c => c.LastName);

Не похоже, чтобы наш список был отсортирован сразу по имени и по фамилии. Выглядит так, как будто второй вызов OrderBy просто перезатер результаты первой сортировки и это на самом деле так. Дело в том, что вызов этого метода сортировки всегда переупорядочивает входную последовательность, т.е. сколько раз OrderBy будет вызван, столько раз последовательность будет отсортирована.

Настало время ближе познакомиться с методом ThenBy, который производит дополнительную сортировку входящей последовательности.

public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(
	this IOrderedEnumerable<TSource> source,
	Func<TSource, TKey> keySelector
)

Как видим этот метод является расширением для IOrderedEnumerable, т.е. мы не сможем использовать ThenBy без использования OrderBy.

Заменим второй вызов OrderBy на ThenBy и посмотрим что выйдет.

var orderedUsers = users.OrderBy(c => c.FirstName).ThenBy(c => c.LastName);

Не сложно заметить, что наша последовательность отсортирована по имени как первичному ключу сортировки и дополнительно произведена сортировка по фамилиям. Можно сделать вывод, что для первичной сортировки мы всегда должны использовать OrderBy, а затем для отсортированной последовательности применять столько методов ThenBy сколько нам нужно.

Комментарии

Оставить комментарий