在LINQ中应用任意数量的OrderBy()

Did*_*xis 1 .net c# linq ienumerable extension-methods

我写了一个扩展方法,可以采用任意数字或OrderBy()并递归应用它们....

我最好展示一个例子:

public static IEnumerable<User> ApplyOrdering(this IEnumerable<User> users,
                                              int index,
                                              params Func<User, string>[] sorts)
{
    if(index == sorts.Length)
        return users;

    users = users.OrderBy(sorts[index]);
    index++;
    return users.ApplyOrdering(index, sorts);
}

// And it's called like this:
void Example()
{
    var users = GetUnsortedUsers();

    var sortedUsers = users.ApplyOrdering(0, u => u.DisplayName,
                                             u => u.Username,
                                             u => u.Email);
}
Run Code Online (Sandbox Code Playgroud)

这不是一个问题,但我想知道这是否可以以更好,更优雅的方式完成?

首先,我不喜欢在方法调用中声明起始索引.另一个可能的挑剔是必须调用.ApplyOrdering(),最后一次只是为了返回用户.

你觉得怎么样?!我很想看到C#大师们提出的一些聪明的解决方案!

编辑:我知道你们中的一些人会指出,只需编写这样的查询就会更好,更具表现力:

var orderedUsers = users.OrderBy(u => u.DisplayName)
                        .ThenBy(u => u.Username)
                        .ThenBy(u => u.Email);
Run Code Online (Sandbox Code Playgroud)

但在我的场景中,过滤器的数量和类型并不总是相同,所以我需要一个可以容纳任意数量的过滤器的通用解决方案.

Jon*_*eet 6

目前它已被打破 - 它将有效地向后应用订购.我怀疑你想要:

// Slightly more generic, although it's still requiring projections to string...
public static IEnumerable<T> ApplyOrdering<T>(this IEnumerable<T> source,
                                              params Func<T, string>[] sorts)
{
    // TODO: Argument validation
    if (sorts.Length == 0)
    {
        return source;
    }

    IOrderedEnumerable<T> ordered = source.OrderBy(sorts[0]);
    foreach (var ordering in sorts.Skip(1))
    {
        ordered = ordered.ThenBy(ordering);
    }
    return ordered;
}
Run Code Online (Sandbox Code Playgroud)