Могу ли я улучшить эти методы расширения Pagination?

Я только что написал несколько методов расширения страниц, и мне было любопытно узнать, есть ли какие-либо улучшения, которые я мог бы сделать.

Я очень доволен базовым методом разбивки на страницы, где вы указываете как размер страницы, так и номер страницы (как показано ниже)

    public static IEnumerable<T> Paginate<T>(this IEnumerable<T> source, int pageSize, int pageNumber)
    {
        if (pageSize == 0) throw new ArgumentOutOfRangeException("pageSize");
        if (pageNumber == 0) throw new ArgumentOutOfRangeException("pageNumber");

        return source.Skip(pageSize * (pageNumber - 1)).Take(pageSize);
    }

но мне было интересно, есть ли лучший способ сделать "авто" разбиение на страницы, где он возвращает IEnumerable<IEnumerable<T>>

    public static IEnumerable<IEnumerable<T>> Paginate<T>(this IEnumerable<T> source, int pageSize)
    {
        source.ThrowIfNull("source");
        if (pageSize == 0) throw new ArgumentOutOfRangeException("pageSize");

        var pageCount = (int)Math.Ceiling(source.Count() / (double)pageSize);

        if (pageSize == 1)
            pageCount = source.Count();

        for (int i = 1; i <= pageCount; i++)
        {
            yield return source.Paginate(pageSize, i);
        }
    }

Кажется немного подозрительным, что нужно повторять итерацию дважды (один раз для подсчета и один раз для возврата урожая.

Есть ли очевидный способ улучшить эти методы?

Ответ 1

Взгляните на MoreLinq Batch: - http://code.google.com/p/morelinq/source/browse/trunk/MoreLinq/Batch.cs?r=84

Что реализовано как:

public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
              this IEnumerable<TSource> source, int size)
{
  TSource[] bucket = null;
  var count = 0;

  foreach (var item in source)
  {
      if (bucket == null)
          bucket = new TSource[size];

      bucket[count++] = item;
      if (count != size)
          continue;

      yield return bucket;

      bucket = null;
      count = 0;
  }

  if (bucket != null && count > 0)
      yield return bucket.Take(count);
}