I’ve got two extensions for IEnumerable:
public static class IEnumerableGenericExtensions
{
public static IEnumerable<IEnumerable<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
List<T> toReturn = new List<T>(max);
foreach (var item in source)
{
toReturn.Add(item);
if (toReturn.Count == max)
{
yield return toReturn;
toReturn = new List<T>(max);
}
}
if (toReturn.Any())
{
yield return toReturn;
}
}
public static int IndexOf<T>(this IEnumerable<T> source, Predicate<T> searchPredicate)
{
int i = 0;
foreach (var item in source)
if (searchPredicate(item))
return i;
else
i++;
return -1;
}
}
Then I write this code:
Pages = history.InSetsOf<Message>(500);
var index = Pages.IndexOf(x => x == Pages.ElementAt(0));
where
public class History : IEnumerable
But as a result I’ve got not ‘0’ as I’ve expected, but ‘-1’. I cant understand – why so?
When you write
Pages.IndexOf(x => x == Pages.ElementAt(0));, you actually runInSetsOfmany times, due to deferred execution (aka lazy). To expand:Pages = history.InSetsOf<Message>(500)– this line doesn’t runInSetsOfat all.Pages.IndexOf– Iterates overPages, so it starts executingInSetsOfonce.x == Pages.ElementAt(0)– this executesInSetsOfagain, once for every element in the collection ofPages(or at least untilsearchPredicatereturn true, which doesn’t happen here).Each time you run
InSetsOfyou create a new list (specifically, a new first list, because you useElementAt(0)). These are two different objects, so comparison of==between them fails.An extremely simple fix would be to return a list, so
Pagesis not a deferred query, but a concrete collection:Another option is to use
SequenceEqual, though I’d recommend caching the first element anyway: