--- trunk/libxmltv/Extensions.cs 2013/03/16 21:53:19 196
+++ trunk/libxmltv/Extensions.cs 2013/03/16 22:02:01 197
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Diagnostics;
namespace libxmltv
{
@@ -28,16 +29,50 @@ namespace libxmltv
public static class extensions
{
- ///
- /// Break a list of items into chunks of a specific size
- ///
- public static IEnumerable> Chunk(this IEnumerable source, int chunksize)
+ public static IEnumerable> Chunk(this IEnumerable source,
+ int chunkSize)
{
- while (source.Any())
+ // Validate parameters.
+ if (source == null) throw new ArgumentNullException("source");
+ if (chunkSize <= 0) throw new ArgumentOutOfRangeException("chunkSize",
+ "The chunkSize parameter must be a positive value.");
+
+ // Call the internal implementation.
+ return source.ChunkInternal(chunkSize);
+ }
+ private static IEnumerable> ChunkInternal(this IEnumerable source, int chunkSize)
+ {
+ // Validate parameters.
+ Debug.Assert(source != null);
+ Debug.Assert(chunkSize > 0);
+
+ // Get the enumerator. Dispose of when done.
+ using (IEnumerator enumerator = source.GetEnumerator())
+ do
+ {
+ // Move to the next element. If there's nothing left
+ // then get out.
+ if (!enumerator.MoveNext()) yield break;
+
+ // Return the chunked sequence.
+ yield return ChunkSequence(enumerator, chunkSize);
+ } while (true);
+ }
+ private static IEnumerable ChunkSequence(IEnumerator enumerator, int chunkSize)
+ {
+ // Validate parameters.
+ Debug.Assert(enumerator != null);
+ Debug.Assert(chunkSize > 0);
+
+ // The count.
+ int count = 0;
+
+ // There is at least one item. Yield and then continue.
+ do
{
- yield return source.Take(chunksize);
- source = source.Skip(chunksize);
- }
+ // Yield the item.
+ yield return enumerator.Current;
+ } while (++count < chunkSize && enumerator.MoveNext());
}
}
}