2008-12-23 95 views
66

我有一個方法,它給出參數「bool sortAscending」。現在我想用LINQ根據這個參數創建排序列表。我當時是這樣的:在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; 

正如你所看到的,這兩個查詢只有「升序」和「 「降」。我想合併兩個查詢,但我不知道如何。有沒有人有答案?

+0

所以,你想有一個查詢既可以做升序還是降序取決於bool sortAsvending值?那是對的嗎。 – 2008-12-23 11:58:23

回答

100

您可以輕鬆的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); 
39

就實現方式而言,這將方法 - 從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到對象)是使用乘數-1/1。這隻對數字數據非常有用,但卻是達到相同結果的厚顏無恥的方式。

+0

我正要寫這個完全一樣的東西,然後我的VS凍結:( – 2008-12-23 12:00:53

+1

使用乘數也失敗了int.MinValue的返回值。 – 2008-12-23 12:09:21

5

有關所需屬性排序倒序什麼,

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

然後做類似

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

它是Reverse()太慢嗎?

0

除了通過@喬恩雙向飛碟給出的美麗解決方案,我還需要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); 
    }