4

Linq で適用する関数を選択することは可能ですか?
私が今持っているものの例:

List<int> list = new List<int>();
bool bDescend = false;
var listOrdered = bDescend ? list.OrderByDescending(it => it) : 
                             list.OrderBy(it => it);

bDescend の値に応じて適用する関数を選択していることがわかります。したがって、実際には 1 つではなく 2 つの Linq クエリがあります。
1つのクエリ内に条件を入れることで回避することはできますか? 多分何かのような

list.ChooseFunction(bDescend ? OrderBy : OrderByDescending)...

実際のコードはより複雑であり、そのようなトリックが可能であれば、コードがはるかに読みやすくなります。
一種のメタプログラミングのように見えます..

4

3 に答える 3

4

独自の Extension メソッドを作成できます。

enum Ordering
{
    Ascending,
    Descending,
}

// trivial to convert to use booleans instead
// of an enum if that's truly what you need
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
    this IEnumerable<TSource> source, Ordering ordering, Func<TSource, TKey> keySelector) 
{
    if (ordering == Ordering.Ascending)
    {
        return source.OrderBy(keySelector);
    }
    else
    {
        return source.OrderByDescending(keySelector);
    }
}

そして、それを次のように呼び出します

var order = Ordering.Descending;
....
MyList.OrderBy(order, it => it);

それ以外に、ChooseFunction型を作ることは可能ですが、それは次のように見える必要がChooseFunction(bdescend ? "OrderBy" : "OrderByDescending")あり、関数名を参照するこれらの魔法の文字列がどれほど醜いかについては知りたくありません。また、ChooseFunction 拡張機能をハードコーディングするか、やろうとしている単純なことに対してとてつもなく高価なリフレクションに頼る必要があります。

于 2012-11-01T02:03:46.510 に答える
2

昇順と降順の2つの比較子を作成し、そのうちの1つをOrderByメソッドに渡すことができます。

list.OrderBy(it => it, asc ? new AscComparer() : new DescComparer())
于 2012-11-01T02:12:30.720 に答える
0

拡張メソッドの構文を失うことを気にしない場合は、デリゲートを使用して並べ替えメソッドを指定できます。

List<int> list = new List<int>();

Func<IEnumerable<int>, Func<int, int>,IEnumerable<int>> sorter;
if (cond)
{
   sorter = Enumerable.OrderBy<int, int>;
}
else
{
   sorter = Enumerable.OrderByDescending<int, int>;
}

var sorted = sorter(list, _ => _);
于 2012-11-05T20:01:49.977 に答える