Как отсортировать List<T> по свойству объекта в C#?
Сортировка списка объектов в C#: несколько способов
Ваша проблема типична для новичков. Метод List.Sort() действительно не может сортировать объекты пользовательских классов без дополнительной информации. Есть несколько надёжных способов решить эту задачу. Рассмотрим самые популярные.
Способ 1: LINQ (рекомендуется для большинства случаев)
Самый простой и читаемый способ — использовать LINQ-методы OrderBy и ThenBy. Они не изменяют исходный список, а возвращают новую отсортированную коллекцию.
using System.Linq;
// Сортировка по возрастанию возраста
List<Person> sortedPeople = people.OrderBy(p => p.Age).ToList();
// Сортировка по убыванию возраста
List<Person> sortedDesc = people.OrderByDescending(p => p.Age).ToList();
// Сортировка по нескольким полям (сначала по возрасту, потом по имени)
List<Person> sortedMulti = people
.OrderBy(p => p.Age)
.ThenBy(p => p.Name)
.ToList();
Преимущества: очень читаемый код, не изменяет исходный список, легко комбинировать условия.
Способ 2: Сортировка на месте с помощью Comparison<T>
Если нужно отсортировать исходный список без создания нового, используйте перегрузку Sort(), принимающую делегат Comparison<T>.
// Сортировка по возрастанию возраста (изменяет исходный список)
people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
// Сортировка по убыванию
people.Sort((p1, p2) => p2.Age.CompareTo(p1.Age));
// Сортировка по имени (строки)
people.Sort((p1, p2) => p1.Name.CompareTo(p2.Name));
Этот способ изменяет исходный список, что может быть полезно для экономии памяти.
Способ 3: Реализация IComparer<T>
Для многоразового использования или сложной логики сравнения создайте отдельный класс-компаратор.
public class PersonAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Age.CompareTo(y.Age); // по возрастанию
// return y.Age.CompareTo(x.Age); // по убыванию
}
}
// Использование:
people.Sort(new PersonAgeComparer());
Какой способ выбрать?
- Для простой сортировки без изменения исходного списка — используйте LINQ (
OrderBy). - Если нужно изменить исходный список — используйте
Sortс лямбда-выражением. - Для сложной или часто используемой логики сортировки — создайте свой
IComparer.
Пример полного рабочего кода:
List<Person> people = new List<Person>
{
new Person { Name = "Анна", Age = 30 },
new Person { Name = "Борис", Age = 25 },
new Person { Name = "Виктор", Age = 35 }
};
// LINQ сортировка (создаёт новый список)
var sortedByAge = people.OrderBy(p => p.Age).ToList();
// Сортировка на месте
people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
// Вывод результата
foreach (var person in people)
Console.WriteLine($"{person.Name}: {person.Age}");
// Вывод: Борис: 25, Анна: 30, Виктор: 35
<<Альтернативный подход: реализация IComparable<T> в самом классе
Если вам нужно, чтобы объекты вашего класса всегда сортировались по определённому правилу (например, по умолчанию по возрасту), можно реализовать интерфейс IComparable<T> прямо в классе Person.
public class Person : IComparable<Person>
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Person other)
{
if (other == null) return 1;
return this.Age.CompareTo(other.Age); // сортировка по возрасту
}
}
// Теперь можно писать просто:
people.Sort(); // работает!
Плюсы: очень простое использование — достаточно вызвать Sort() без параметров.
Минусы: вы жёстко задаёте логику сортировки в классе. Если понадобится сортировать по другому полю (например, по имени), придётся использовать другие способы. Кроме того, этот подход нарушает принцип единственной ответственности (класс не должен одновременно хранить данные и определять логику их сравнения).
Рекомендую использовать этот способ только для простых случаев, когда сортировка по одному полю является "естественным" порядком для вашего класса (например, для числовых идентификаторов).
Ответов пока нет.
Войдите чтобы оставить ответ