我已经编写了一个扩展方法,可以接受任意数字或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);
}
不是个问题,但我想知道这是否可以用一种更好、更优雅的方式来完成?
首先,我不喜欢在方法调用中声明起始索引。另一个可能的缺点是最后一次调用. applyordering()只是为了返回用户。
你觉得呢?我很想看到你们这些c#大师想出一些聪明的解决方案!
编辑:我知道你们中的一些人会指出,这样写查询更好,更有表现力:var orderedUsers = users.OrderBy(u => u.DisplayName)
.ThenBy(u => u.Username)
.ThenBy(u => u.Email);
但是在我的场景中,过滤器的数量和类型并不总是相同的,所以我需要一个通用的解决方案,可以容纳任何数量的过滤器
目前是破碎 -它将有效地应用排序向后。我怀疑你想要:
// 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;
}
您的代码不起作用,您的列表将仅按您设置的最后一个OrderBy排序。
第一个必须使用OrderBy,其他的必须使用ThenBy。
这就是我要做的
public static IEnumerable<User> ApplyOrdering(this IEnumerable<User> users, params Func<User, string>[] sorts)
{
var sorted = users.OrderBy(sorts[0]);
for(int i = 1; i < sorts.length; i++)
{
sorted = sorted.ThenBy(sorts[i]);
}
return sorted;
}
我没有花时间测试我的代码,我相信有更好的解决方案。