diff --git a/src/Umbraco.Core/EnumerableExtensions.cs b/src/Umbraco.Core/EnumerableExtensions.cs index dfdd26cd84..2aba7684f0 100644 --- a/src/Umbraco.Core/EnumerableExtensions.cs +++ b/src/Umbraco.Core/EnumerableExtensions.cs @@ -17,21 +17,41 @@ namespace Umbraco.Core throw new NullReferenceException("source"); // enumerate the source only once! - var enumerator = source.GetEnumerator(); - - while (enumerator.MoveNext()) - yield return EnumerateGroup(enumerator, groupSize); + return new InGroupsEnumerator(source, groupSize).Groups(); } - private static IEnumerable EnumerateGroup(IEnumerator enumerator, int count) + // this class makes sure that the source is enumerated only ONCE + // which means that when it is enumerated, the actual groups content + // has to be evaluated at the same time, and stored in an array. + private class InGroupsEnumerator { - var c = 1; - do - { - yield return enumerator.Current; - } while (c++ < count && enumerator.MoveNext()); - } + private readonly IEnumerator _source; + private readonly int _count; + private bool _mightHaveNext; + public InGroupsEnumerator(IEnumerable source, int count) + { + _source = source.GetEnumerator(); + _count = count; + _mightHaveNext = true; + } + + public IEnumerable> Groups() + { + while (_mightHaveNext && _source.MoveNext()) + yield return Group().ToArray(); // see note above + } + + private IEnumerable Group() + { + var c = 0; + do + { + yield return _source.Current; + } while (++c < _count && _source.MoveNext()); + _mightHaveNext = c == _count; + } + } /// The distinct by. /// The source.