如何传递OrderBy(), Where()等,作为处理集合的参数

本文关键字:处理 集合 参数 Where 何传递 OrderBy | 更新日期: 2023-09-27 18:10:11

我有以下代码:

class Program
{
    static void Main(string[] args)
    {
        List<int> li = new List<int>() { 1,2,3,4,5,6,7,8,9,10 };
        ProcessCollection(li, x => x);
    }
    static IEnumerable<TSource> ProcessCollection<TSource,TResult>(IEnumerable<TSource> c, Func<TSource, TResult> lambdaexp)
    {
        return c.OrderBy(lambdaexp);
    }
}
如您所见,它接受一个集合,处理它并返回新集合。当前通过OrderBy()扩展方法处理集合。

我想扩展这个函数,这样它就可以接受另一个(第三个)参数作为函数,并将这个函数应用于作为第一个参数传递的集合。到目前为止,我一直在尝试用Func<>Action<>的组合,但我不能算出来。我还是初学者。

是否有可能定义ProcessCollection的参数,以便它根据作为参数传递的函数处理集合?

谢谢。

如何传递OrderBy(), Where()等,作为处理集合的参数

你可以这样做:

static IEnumerable<TElemType> Process<TElemType>(IEnumerable<TElemType> source, 
    params Func<IEnumerable<TElemType>, IEnumerable<TElemType>>[] funcs)
{
    foreach(var func in funcs)
        source = func(source);
    return source;
}

并像这样使用:

List<int> li = new List<int>() { 1,2,3,4,5,6,7,8,9,10 };
Process(li, x => x.OrderBy(y => y), x => x.Reverse());

但我真的不确定为什么这样做比直接做更好:

li.OrderBy(y => y).Reverse()

它们具有不同的签名,编译器必须始终知道返回类型是什么。除非您想使用显式强制转换并在此过程中损害您自己,或者更好地使用反射,否则我建议您进一步考虑您试图实现的目标,然后考虑更好的解决方案来实现它。

当然可以,这很简单:

static IEnumerable<TResult> ProcessCollection<TSource,TResult>
  (IEnumerable<TSource> c, Func<IEnumerable<TSource>, IEnumerable<TResult>> func)
{
    return func(c);
}

换句话说,不是传递一个应用于每个元素的函数,而是传递一个转换整个枚举对象的函数。你可以这样调用它,例如:

ProcessCollection(new [] { 1, 2, 3 }, c => c.OrderBy(i => i));

如果你想同时应用更多的转换,只需将它们链接在一起(这就是LINQ,真的):

ProcessCollection(new [] { 1, 2, 3 }, c => c.Select(i => i.ToString()).OrderBy(i => i));

当然,这没什么用。它所做的事情与简单地执行

完全相同
new [] { 1, 2, 3 }.Select(i => i.ToString()).OrderBy(i => i);
首先是

。即使你在你的ProcessCollection方法中做一些实际的处理,你通常只使用这样的东西:

new [] { 1, 2, 3 }.Process().Select(i => i.ToString()).OrderBy(i => i)

你可以这样做:

void Main(string[] args)
{
    List<int> li = new List<int>() { 1,2,3,4,5,6,7,8,9,10 };
    Func<int, bool> whereFilter = x => x % 2 == 0;
    Func<int, string> orderByClause = x => x.ToString();
    ProcessCollection(li, whereFilter, orderByClause); // 10, 2, 4, 6, 8
}
static IEnumerable<TSource> ProcessCollection<TSource, TResult>(     
    IEnumerable<TSource> source,
    Func<TSource, bool> whereFilter = null, 
    Func<TSource, TResult> orderByClause = null)
{
    if (whereFilter != null) source = source.Where(whereFilter);
    if (orderByClause != null) source = source.OrderBy(orderByClause);
    return source;
}