Как отсортировать List<T> по свойству объекта в C#?
Использование LINQ: OrderBy и OrderByDescending
Самый простой и современный способ сортировки списка объектов по свойству — использование LINQ-методов OrderBy (по возрастанию) и OrderByDescending (по убыванию). Они не изменяют исходный список, а возвращают новую отсортированную последовательность.
using System;
using System.Collections.Generic;
using System.Linq;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
List<Person> people = new List<Person>
{
new Person { Name = "Анна", Age = 25 },
new Person { Name = "Борис", Age = 30 },
new Person { Name = "Виктор", Age = 20 }
};
// Сортировка по возрастанию Age
var sortedByAge = people.OrderBy(p => p.Age).ToList();
// Сортировка по убыванию Age
var sortedByAgeDesc = people.OrderByDescending(p => p.Age).ToList();
// Сортировка по нескольким полям: сначала Age, потом Name
var sortedMulti = people.OrderBy(p => p.Age).ThenBy(p => p.Name).ToList();
// Вывод результата
Console.WriteLine("По возрастанию возраста:");
foreach (var person in sortedByAge)
Console.WriteLine($"{person.Name}: {person.Age}");
Console.WriteLine("\nПо убыванию возраста:");
foreach (var person in sortedByAgeDesc)
Console.WriteLine($"{person.Name}: {person.Age}");
}
}
Сортировка с изменением исходного списка: Sort + Comparison
Если нужно отсортировать исходный список (без создания нового), используйте перегрузку List.Sort(Comparison<T>):
// Сортировка по возрастанию Age (изменяет исходный список)
people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
// Сортировка по убыванию Age
people.Sort((p1, p2) => p2.Age.CompareTo(p1.Age));
// Сортировка по строковому свойству Name
people.Sort((p1, p2) => p1.Name.CompareTo(p2.Name));
Реализация IComparable<T> в классе
Если ваш класс всегда должен сортироваться по одному и тому же свойству, реализуйте интерфейс IComparable<T>:
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() без аргументов
people.Sort();
Важные моменты:
- LINQ (OrderBy) — не изменяет исходный список, возвращает
IEnumerable<T>. Для получения списка вызовите.ToList(). - Sort() — изменяет исходный список, работает быстрее, но менее гибко.
- Для сортировки по нескольким полям используйте цепочку
OrderBy().ThenBy()илиOrderByDescending().ThenByDescending(). - Для обратной сортировки можно использовать
.Reverse()послеOrderBy().
Альтернативный подход: использование LINQ Query Syntax
Помимо методов расширения (лямбда-выражений), вы можете использовать синтаксис LINQ-запросов, который более читаем для некоторых разработчиков:
var sortedPeople = from p in people
orderby p.Age ascending, p.Name descending
select p;
List<Person> result = sortedPeople.ToList();
Здесь ascending (по умолчанию) — сортировка по возрастанию, descending — по убыванию. Можно комбинировать несколько полей.
Сортировка с помощью IComparer
Если логика сортировки сложная или должна переиспользоваться, создайте отдельный класс компаратора:
public class PersonAgeComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
if (x == null || y == null) return 0;
return x.Age.CompareTo(y.Age);
}
}
// Использование
people.Sort(new PersonAgeComparer());
Этот подход удобен, когда требуется много раз сортировать одинаковым образом или когда логика сравнения изменяется в зависимости от контекста.