【问题标题】:Passing type members generically to operate on generic collection泛型传递类型成员以对泛型集合进行操作
【发布时间】:2013-08-15 19:51:35
【问题描述】:

我正在创建一个函数,它将获取一些 IEnumerable、进行分组、排序、获取一些前 N 个元素并返回这些元素的列表。以后它可能会做更多的事情,这就是为什么我想把它变成一个函数而不是直接使用 LINQ。

我依靠匿名委托来指定 T 类型的哪些成员将用于对集合进行分组和排序。

    public IEnumerable<T> GetList(IEnumerable<T> collection, Func<T, object> groupBy, Func<T, object> orderBy, int howMany)
    {
        var group = collection
            .GroupBy(groupBy)
            .Select(x => x.OrderBy(orderBy).Take(howMany))
            .Aggregate((l1, l2) => l1.Concat(l2));

        return group.ToList();
    }

并像这样使用:

        new CollectionGroupPicker<NumericDomainObject>().GetList(list, x => x.GroupableField, x => x.OrderableField, 2).ToList();

我的问题是 - 有没有更好的方法来传递我将使用哪个 T 类型的成员来分组和排序?我在这里使用对象,但是有更好的方法吗?

【问题讨论】:

  • 我很难看到“更好的方法”。您的解决方案看起来非常简洁。
  • 我建议的唯一更改是制作具有IEnumerable&lt;T&gt; GetList(IQueryable&lt;T&gt; collection, Expression&lt;Func&lt;T, object&gt;&gt; groupBy, Expression&lt;Func&lt;T, object&gt;&gt; orderBy, int howMany) 方法签名的第二个版本,以便您可以将它与LinqToEntities(即:实体框架、LinqToSql 等)一起使用。 (加上像答案建议的那样用另一个通用参数切换object
  • @ScottChamberlain - 谢谢。那是我为了测试而记下的一个愚蠢的 ToList()。更改为返回组。
  • 如果您要返回组,并且按照我的建议使用 IQueryable 版本,请务必将返回类型也更改为 IQueryable&lt;T&gt;

标签: c# linq generics collections anonymous-delegates


【解决方案1】:

您应该指定组并选择键作为通用参数,而不是指定object。它们的类型将根据使用情况自动推断,调用者可以指定具有任何返回类型的 lambda。

public IEnumerable<T> GetList<TGroupKey, TOrderKey>(IEnumerable<T> collection, 
                                                    Func<T, TGroupKey> groupBy, 
                                                    Func<T, TOrderKey> orderBy, 
                                                    int howMany)
{
    var group = collection
        .GroupBy(groupBy)
        .Select(x => x.OrderBy(orderBy).Take(howMany))
        .Aggregate((l1, l2) => l1.Concat(l2));
    return group.ToList();
}

【讨论】:

    【解决方案2】:

    我同意 Samuel 使用通用参数类型。另外,为什么不使用SelectMany 来展平结果,或者将其作为扩展方法?

    static class GetListExtensionMethods
    {
        public static IEnumerable<T> GetList<T, TGroupingField, TOrderingField>(this IEnumerable<T> collection, Func<T, TGroupingField> groupBy, Func<T, TOrderingField> orderBy, int howMany)
        {
            var group = collection
                .GroupBy(groupBy)
                .SelectMany(x => x.OrderBy(orderBy).Take(howMany));
            return group.ToList();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-04-13
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多