/// <summary>
        /// Splits a source <see cref="IEnumerable{T}"/> into several <see cref="IList{T}"/>s
        /// with a max size of batchSize.
        /// <remarks>Note that batchSize must be one or larger.</remarks>
        /// </summary>
        /// <param name="source">A sequence of values to split into smaller batches.</param>
        /// <param name="batchSize">The number of elements to place in each batch.</param>
        /// <returns>The original collection, split into batches.</returns>
        public static IEnumerable <IList <T> > Batch <T>(this IEnumerable <T> source, int batchSize)
        {
            ArgumentUtility.CheckForNull(source, nameof(source));
            ArgumentUtility.CheckBoundsInclusive(batchSize, 1, int.MaxValue, nameof(batchSize));

            var nextBatch = new List <T>(batchSize);

            foreach (T item in source)
            {
                nextBatch.Add(item);
                if (nextBatch.Count == batchSize)
                {
                    yield return(nextBatch);

                    nextBatch = new List <T>(batchSize);
                }
            }

            if (nextBatch.Count > 0)
            {
                yield return(nextBatch);
            }
        }