Что такое ThenBy в LINQ?

Ответ

ThenBy — это метод расширения LINQ, который применяется для последующей сортировки по дополнительному ключу после первичной сортировки, выполненной методами OrderBy или OrderByDescending. Он возвращает интерфейс IOrderedEnumerable<T>.

Синтаксис и пример:

class Employee
{
    public string Department { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
}

var employees = new List<Employee>
{
    new Employee { Department = "IT", Name = "Charlie", Salary = 60000 },
    new Employee { Department = "HR", Name = "Alice", Salary = 55000 },
    new Employee { Department = "IT", Name = "Bob", Salary = 70000 },
    new Employee { Department = "IT", Name = "Alice", Salary = 65000 }
};

// Сортировка по отделу (по возрастанию), затем по имени (по возрастанию),
// затем по зарплате (по убыванию)
var sortedEmployees = employees
    .OrderBy(e => e.Department)          // Первичный ключ
    .ThenBy(e => e.Name)                 // Вторичный ключ
    .ThenByDescending(e => e.Salary);    // Третичный ключ (по убыванию)

/* Результат:
   Department: HR,  Name: Alice, Salary: 55000
   Department: IT,  Name: Alice, Salary: 65000
   Department: IT,  Name: Bob,   Salary: 70000
   Department: IT,  Name: Charlie, Salary: 60000
*/

Ключевые особенности:

  • Работает только после OrderBy: Вызов ThenBy без предшествующего OrderBy/OrderByDescending вызовет ошибку компиляции.
  • Ленивое выполнение: Сортировка происходит только в момент перечисления результатов (например, в цикле foreach или при вызове ToList()).
  • Стабильность: Методы сортировки LINQ являются стабильными. Это означает, что если два элемента имеют одинаковые ключи, их относительный порядок из исходной коллекции сохраняется.
  • Аналог для SQL: Соответствует конструкции ORDER BY Department, Name, Salary DESC в SQL.

ThenBy и ThenByDescending — незаменимые инструменты для реализации многоуровневой сортировки данных в запросах LINQ.

Ответ 18+ 🔞

Давай разжую про этот ThenBy, а то некоторые до сих пор не въезжают, как эта штука работает. Представь, что у тебя куча сотрудников, и ты их сначала по отделам раскидал — вроде логично, да? А потом смотришь: в отделе «IT» сидят три оболтуса, и все вразнобой. Вот тут-то ThenBy и пригодится — это как сказать: «Ладно, по отделам разложил, а теперь внутри каждого отдела давай по алфавиту, сука!»

Смотри, вот тебе живые люди:

class Employee
{
    public string Department { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
}

var employees = new List<Employee>
{
    new Employee { Department = "IT", Name = "Charlie", Salary = 60000 },
    new Employee { Department = "HR", Name = "Alice", Salary = 55000 },
    new Employee { Department = "IT", Name = "Bob", Salary = 70000 },
    new Employee { Department = "IT", Name = "Alice", Salary = 65000 }
};

Хочешь красиво отсортировать? Берёшь:

var sortedEmployees = employees
    .OrderBy(e => e.Department)          // Сначала по отделам
    .ThenBy(e => e.Name)                 // Потом по имени внутри отдела
    .ThenByDescending(e => e.Salary);    // А если имена совпали — по зарплате, но сверху жирные коты!

И получаешь порядок, от которого глаз радуется:

HR,  Alice, 55000
IT,  Alice, 65000  ← видишь, две Алисы, но у одной зарплата больше — она и выше!
IT,  Bob,   70000
IT,  Charlie, 60000

Важный момент, блядь: ThenBy не работает сам по себе! Это как прийти в бар и сказать: «Мне, пожалуйста, потом». Тебя пошлют нахуй! Сначала надо OrderBy вызвать, а уже потом цеплять ThenBy. Иначе компилятор тебе такую ошибку влепит — мама не горюй.

И ещё запомни: сортировка в LINQ — стабильная. Это научное слово означает, что если у двух элементов ключи одинаковые (например, два Ивана в одном отделе), то они останутся в том же порядке, в котором были в исходной коллекции. Не будет он их как попало перетасовывать, уважает твою изначальную хрень.

Короче, если в SQL ты писал ORDER BY Department, Name, Salary DESC, то тут — то же самое, только по-шарповому. Удобная хуйня, в общем.