С# обобщенный порядок

Я хочу создать обобщенный метод для сортировки любого списка по любой переменной.

Например. У меня есть объект Student и Class:

Order(studentList, s => s.Name, desc)
Order(classList, s => s.ClassName, desc)

Я попытался создать частный метод для этого:

private List<T> Order<T, TKey>(List<T> listToOrder, Expression<Func<T, TKey>> sortKey, bool desc)
{
   return desc ? listToOrder.OrderByDescending(sortKey) : listToOrder.OrderBy(sortKey)
}

Но это явно не работает. Любые идеи, как я могу этого добиться? Отредактирует ответ, если его недостаточно.

Что не работает? У вас есть исключение?

Selim Yildiz 23.03.2022 08:56

Кажется, ваш метод предполагает, что T является списком, а также параметром типа... а методы OrderBy и OrderByDescending не возвращают списки, они возвращают последовательности. Далее, «это, очевидно, не работает» не так описательно, как полное описание того, что вы видите. Наконец, я бы предложил использовать здесь только Func<T, TKey>, а не деревья выражений, если только вам действительно не нужны деревья выражений по какой-то причине, о которой вы нам не сказали.

Jon Skeet 23.03.2022 08:56

Работает без Expression! Большое спасибо :)

newbie 23.03.2022 09:03

Я вообще не вижу никакого преимущества в создании этой функции, поскольку все, что она делает, это вызывает либо OrderByDescending, либо OrderBy. Кроме этого, я не понимаю, почему ваш код не должен работать. Пожалуйста, уточните вашу проблему.

MakePeaceGreatAgain 23.03.2022 09:03

Почему вы используете Expression<Func<T, TKey>> вместо простого Func<T, TKey>? Обычно Expression<Func<T, TKey>> используется, когда у вас есть IQueryable<T>, но у вас его нет.

Enigmativity 23.03.2022 09:12

Я также предлагаю вам изменить bool desc на enum SortDirection { Ascending, Descending }. Тогда ваш код читаем. Order(list, x => x.Name, false) менее читаем, чем Order(list, x => x.Name, SortDirection.Descending).

Enigmativity 23.03.2022 09:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
53
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если ваши значения Student и Class собраны, вы можете попробовать написать метод расширения

  1. возвращаемый тип может быть IOrderedEnumerable<T>, какой тип из OrderBy и OrderByDescending.
  2. вам может не понадобиться использовать Expression просто используйте делегат Func<T, TKey> будет достаточно

как показано ниже

public static class MyExtesion{
    public static IOrderedEnumerable<T> Order<T, TKey>(this IEnumerable<T> source,Func<T, TKey> sortKey, bool desc)
    {
        return desc ? source.OrderByDescending(sortKey) : source.OrderBy(sortKey);
    }
}

Если я правильно понимаю, попробуйте следующее:

    public static List<T> Order<T>(List<T> listToOrder, Func<T, int> sortFunc, bool desc)
    {
        return desc ?
            listToOrder.OrderByDescending(x => sortFunc(x)).ToList() : listToOrder.OrderBy(x => sortFunc(x)).ToList();
    }

Ниже приведены тестовые коды:

var arr1 = new int[] {1,-1,2,-2,0,3,-3};
var result = LogHelper.Order(arr1.ToList(),x=>x*x,false);

Просто зарегистрируйте их.

Другие вопросы по теме