L'utilisation .Skip(...).Take(...)
travaillera pour la pagination. Mais quelque chose à considérer est qu'à nouveau un IEnumerable<...>
recalculera l'énumérable chaque fois qu'il est traité. Est-ce que c'est quelque chose qui est consommé au lieu d'être réinitialisable, vous pourriez avoir des problèmes. Cet ensemble de méthodes peut résoudre ce problème.
public static class EnumerableEx
{
public static IEnumerable<IEnumerable<T>> AsPages<T>(
this IEnumerable<T> set, int pageLength)
{
using (var e = set.GetEnumerator())
while (true)
yield return GetPage(e, pageLength);
}
private static IEnumerable<T> GetPage<T>(
IEnumerator<T> set, int pageLength)
{
for (var position = 0;
position < pageLength && set.MoveNext();
position++)
yield return set.Current;
}
}
... Voici un exemple d'utilisation expliquant pourquoi c'est important.
class Program
{
private static int _last = 0;
private static IEnumerable<int> GetValues()
{
while (true)
yield return _last++;
}
static void Main(string[] args)
{
for (var i = 0; i < 3; i++)
foreach (var value in GetValues().Skip(5 * i).Take(5))
Console.Write(value + ",");
// 0,1,2,3,4,10,11,12,13,14,25,26,27,28,29,
Console.WriteLine();
_last = 0;
foreach (var page in GetValues().AsPages(5).Take(3))
foreach (var value in page)
Console.Write(value + ",");
// 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
}
}
Mere secondes !!! – Will
Cela va itérer sur l'ensemble plusieurs fois si l'objet est 'IEnumerable <>' –
Des scénarios spécifiques pourraient également montrer plus d'efficacité en déplaçant la sélection dans la construction de la boucle. Je ne suis pas sûr non plus dans quels cas. Prendre échouera d'une énumération vide (iow, rowCount étant inutile). – Marc