升序/降序在 LINQ-可以通过参数改变顺序?

我有一个方法,它的参数是“ bool sortAsending”。现在我想使用 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;

正如您所看到的,这两个查询仅在“升序”响应中有所不同。“下降”。我希望合并两个查询,但我不知道如何合并。有人知道答案吗?

162707 次浏览

In terms of how this is implemented, this changes the method - from OrderBy/ThenBy to OrderByDescending/ThenByDescending. However, you can apply the sort separately to the main query...

var qry = from .... // or just dataList.AsEnumerable()/AsQueryable()


if(sortAscending) {
qry = qry.OrderBy(x=>x.Property);
} else {
qry = qry.OrderByDescending(x=>x.Property);
}

Any use? You can create the entire "order" dynamically, but it is more involved...

Another trick (mainly appropriate to LINQ-to-Objects) is to use a multiplier, of -1/1. This is only really useful for numeric data, but is a cheeky way of achieving the same outcome.

You can easily create your own extension method on IEnumerable or 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);
}

Yes, you lose the ability to use a query expression here - but frankly I don't think you're actually benefiting from a query expression anyway in this case. Query expressions are great for complex things, but if you're only doing a single operation it's simpler to just put that one operation:

var query = dataList.OrderByWithDirection(x => x.Property, direction);

What about ordering desc by the desired property,

   blah = blah.OrderByDescending(x => x.Property);

And then doing something like

  if (!descending)
{
blah = blah.Reverse()
}
else
{
// Already sorted desc ;)
}

Is it Reverse() too slow?

In addition to the beautiful solution given by @Jon Skeet, I also needed ThenBy and ThenByDescending, so I am adding it based on his solution:

    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);
}