How do I specify LINQ's OrderBy direction as a boolean?

Viewed 6402

I have a simple data class that has this signature:

internal interface IMyClass {
    string Letter { get; }
    int Number { get; }
}

I wish to be able to sort this data based on a field (specified as string sortField) and a direction (specified as bool isAscending)

Currently I am using a switch (with the ascending logic within each case as if)

IEnumerable<IMyClass> lst = new IMyClass[];//provided as paramater
switch (sortField)
{
    case "letter":
        if( isAscending ) {
            lst = lst.OrderBy( s => s.Letter );
        } else {
            lst = lst.OrderByDescending( s => s.Letter );
        }
        break;
    case "number":
        if( isAscending ) {
            lst = lst.OrderBy( s => s.Number );
        } else {
            lst = lst.OrderByDescending( s => s.Number );
        }
        break;
}

This is pretty ugly, for 2 properties, but when the sort logic differs it becomes a problem (we also see s => s.Number is duplicated twice in the code)

Question What is the best way to pass a boolean to choose the sort direction?

What I've Tried I've ripped apart System.Core.dll and found the OrderBy Extension method implementations:

OrderBy:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
        this IEnumerable<TSource> source, 
        Func<TSource, TKey> keySelector
    ){

    return new OrderedEnumerable<TSource, TKey>(
        source, 
        keySelector, 
        null, 
        false
    );
}

OrderByDescending:

public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
        this IEnumerable<TSource> source, 
        Func<TSource, TKey> keySelector
    ){
        return new OrderedEnumerable<TSource, TKey>(
            source, 
            keySelector, 
            null, 
            true
        );
}

It appears the purpose of having 2 named methods is to abstract this boolean away. I can't create my own extension easily as OrderedEnumberable is internal to System.Core, and writing a layer to go from bool -> methodName -> bool seems wrong to me.

5 Answers
Related