我希望能够编写以下代码:
// contains 500 entries
IList<string> longListOfStrings = ...
// shorterListsOfStrings is now an array of 5 IList<string>,
// with each element containing 100 strings
IList<string>[] shorterListsOfStrings = longListOfStrings.Split(5);
要做到这一点,我必须创建一个名为Split
的通用扩展方法,如下所示:
public static TList[] Split<TList>(this TList source, int elementCount)
where TList : IList<>, ICollection<>, IEnumerable<>, IList, ICollection, IEnumerable
{
return null;
}
但是当我尝试编译时,编译器告诉我IList<>
,ICollection<>
和IEnumerable<>
需要一个类型参数。所以,我将定义更改为以下内容:
public static TList<TType>[] Split<TList<TType>>(this TList<TType> source, int elementCount)
where TList : IList<TType>, ICollection<TType>, IEnumerable<TType>, IList, ICollection, IEnumerable
{
return null;
}
然后编译器抱怨它找不到类型TList
。我有一个想法,我过于复杂的事情,但我看不出如何...任何帮助是值得赞赏的!
答案 0 :(得分:6)
是的,我认为你过于复杂。试试这个:
public static IList<T>[] Split<T>(this IList<T> source, int elementCount)
{
// What the heck, it's easy to implement...
IList<T>[] ret = new IList<T>[(source.Count + elementCount - 1)
/ elementCount];
for (int i = 0; i < ret.Length; i++)
{
int start = i * elementCount;
int size = Math.Min(elementCount, source.Count - i * start);
T[] tmp = new T[size];
// Would like CopyTo with a count, but never mind
for (int j = 0; i < size; j++)
{
tmp[j] = source[j + start];
}
ret[i] = tmp;
}
return ret;
}
毕竟,你不会改变你在基于源的方法中创建的那种列表,不是吗?即使我传入其他一些实现,您也可能会创建List<T>
(或者可能是T[]
)。
您可能希望查看基于IEnumerable<T>
的实施的Batch method in MoreLINQ。
答案 1 :(得分:3)
这个怎么样:
public static IList<TResult>[] Split<TSource, TResult>(
this IList<TSource> source, // input IList to split
Func<TSource, TResult> selector, // projection to apply to each item
int elementCount // number of items per IList
) {
// do something
}
如果你不需要一个版本来投射每个项目:
public static IList<T>[] Split<T>(
this IList<T> source, // input IList to split
int elementCount // number of items per IList
) {
return Split<T, T>(source, x => x, elementCount);
}