Avatar ·

Как отсортировать List<T> по свойству объекта в C#?

Всем привет! Я только начал изучать C# и столкнулся с проблемой при сортировке списка объектов. У меня есть класс `Person` с полями `Name` и `Age`. Я создаю список людей и хочу отсортировать его по возрасту (от младшего к старшему). Вот мой код: ```csharp public class Person { public string Name { get; set; } public int Age { get; set; } } List people = new List { new Person { Name = "Анна", Age = 25 }, new Person { Name = "Борис", Age = 30 }, new Person { Name = "Виктор", Age = 20 } }; // Пытаюсь отсортировать, но не знаю как people.Sort(); // Ошибка: не знает как сравнивать Person ``` Я понимаю, что `Sort()` не знает, по какому полю сортировать. Пробовал использовать `OrderBy`, но тоже не разобрался. Подскажите, как правильно отсортировать список объектов по определённому свойству? Желательно с примерами кода. Заранее спасибо! <<>>

Использование 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());

Этот подход удобен, когда требуется много раз сортировать одинаковым образом или когда логика сравнения изменяется в зависимости от контекста.