如何使用泛型来制作通用的分块算法?

时间:2016-04-29 15:39:53

标签: c# generics

我有两种结构非常相似的方法:

  public static List<List<NodeAttribute>> chunkList(List<NodeAttribute> list, int nSize = 30)
    {
        List<List<NodeAttribute>> chunkedList = new List<List<NodeAttribute>>();

        for (var i = 0; i < list.Count; i += nSize)
        {
            chunkedList.Add(list.GetRange(i, Math.Min(nSize, list.Count - i)));
        }

        return chunkedList;
    }

    public static List<List<int>> chunkList(List<int> list, int nSize = 30)
    {
        List<List<int>> chunkedList = new List<List<int>>();

        for (var i = 0; i < list.Count; i += nSize)
        {
            chunkedList.Add(list.GetRange(i, Math.Min(nSize, list.Count - i)));
        }

        return chunkedList;
    }

理想情况下,我希望有一个通用方法可以获取任何类型的List并返回该类型列表的列表 - 而不是仅仅为我可能需要的每个对象类型添加方法。我知道我可以使用泛型来执行此操作,但是如何使返回类型与输入相同的泛型类型?

2 个答案:

答案 0 :(得分:8)

另一个答案很好地说明了如何使用参数多态 - 您有两种结构相同且仅在类型上有所不同的方法,因此您可以通过创建一个按该类型参数化的方法对其进行泛化。

然而,我们也可以借此机会退后一步,询问我们是否可以解决更普遍的问题。假设您有序列 - 比 List 更通用 - 并且您希望将其分组为序列序列。没有必要限制自己到列表;你可以按任何顺序执行此操作:

public static IEnumerable<IEnumerable<T>> Chunk(
  this IEnumerable<T> items, int size) 
{
  return items
    .Select((item, index) => new { Group = index / size, Item = item })
    .GroupBy(x => x.Group)
    .Select(group => group.Select(g => g.Item));
}

如果你想让它成为一个列表列表,这很容易;将最后一行更改为:

    .Select(group => group.Select(g => g.Item).ToList()).ToList();

答案 1 :(得分:5)

将方法定义为泛型,然后您可以声明参数并使用相同的泛型类型返回。

这样的事情:

public static List<List<T>> ChunkList<T>(List<T> list, int nSize = 30)
{
    List<List<T>> chunkedList = new List<List<T>>();

    for (var i = 0; i < list.Count; i += nSize)
    {
        chunkedList.Add(list.GetRange(i, Math.Min(nSize, list.Count - i)));
    }

    return chunkedList;
}