восходящий / нисходящий в LINQ-можно ли изменить порядок с помощью параметра?
У меня есть метод, который задается параметром "bool sortAscending". Теперь я хочу использовать LINQ для создания отсортированного списка в зависимости от этого параметра. Я получил тогда это:
var ascendingQuery = from data in dataList
orderby data.Property ascending
select data;
var descendingQuery = from data in dataList
orderby data.Property descending
select data;
Как вы можете видеть, оба запроса отличаются только "восходящие" респ. "нисходящий." Я хочу объединить оба запроса, но я не знаю как. У кого-нибудь есть ответ?
4 ответа:
вы можете легко создать свой собственный метод расширения на IEnumerable или IQueryable:
public static IOrderedEnumerable<TSource> OrderByWithDirection<TSource,TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool descending) { return descending ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector); } public static IOrderedQueryable<TSource> OrderByWithDirection<TSource,TKey> (this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, bool descending) { return descending ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector); }
Да, вы теряете возможность использовать выражение запроса здесь - но, честно говоря, я не думаю, что вы на самом деле пользуетесь выражением запроса в любом случае в этом случае. Выражения запросов отлично подходят для сложных вещей, но если вы делаете только одну операцию, проще просто поставить эту операцию:
var query = dataList.OrderByWithDirection(x => x.Property, direction);
С точки зрения того, как это реализовано, это изменяет метод - от OrderBy / ThenBy к OrderByDescending / ThenByDescending. Однако сортировку можно применить отдельно к основному запросу...
var qry = from .... // or just dataList.AsEnumerable()/AsQueryable() if(sortAscending) { qry = qry.OrderBy(x=>x.Property); } else { qry = qry.OrderByDescending(x=>x.Property); }
какая-то польза? Вы можете создать весь" заказ " динамически, но он более вовлечен...
еще один трюк (в основном подходит для LINQ-to-Objects) - использовать множитель, равный -1/1. Это действительно полезно только для числовых данных, но это дерзкий способ достижение того же результата.
Как насчет заказа desc по нужному свойству,
blah = blah.OrderByDescending(x => x.Property);
и потом делать что-то вроде
if (!descending) { blah = blah.Reverse() } else { // Already sorted desc ;) }
это обратный() слишком медленно?
в дополнение к прекрасному решению, данному @Jon Skeet, мне также нужны ThenBy и ThenByDescending, поэтому я добавляю его на основе своего решения:
public static IOrderedEnumerable<TSource> ThenByWithDirection<TSource, TKey>( this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, bool descending) { return descending ? source.ThenByDescending(keySelector) : source.ThenBy(keySelector); }