IgorStack
IgorStack

Reputation: 869

Extension to choose which extension to use in Linq

Is it possible to choose which function to apply in Linq?
Example of what I now have:

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

You see that I choose which function to apply depending on bDescend value - so there is actually two Linq queries, not one.
Is it possible to avoid it by putting condition inside one query? Maybe something like

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

Real code is more compliated and if such trick possible it would make code much more readable.
Looks like kind of metaprogramming..

Upvotes: 4

Views: 92

Answers (3)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249656

If you don't mind loosing the extension method syntax you could use a delegate to specify the sorting method:

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, _ => _);

Upvotes: 0

Earlz
Earlz

Reputation: 63835

You could create your own Extension method:

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

And then call it like

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

Other than that, it's possible to make a ChooseFunction type thing, but it'd have to look like ChooseFunction(bdescend ? "OrderBy" : "OrderByDescending") and I don't even want to get into how ugly those magic strings referring to function names are. You'd also have to either hard code the ChooseFunction extension, or rely on reflection which is ridiculously expensive for the simple thing you're trying to do

Upvotes: 4

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56162

You can create 2 Comparers: ascending and descending, then pass one of them to OrderBy method, i.e.:

list.OrderBy(it => it, asc ? new AscComparer() : new DescComparer())

Upvotes: 2

Related Questions