From 5d3a82a33ad454a36acf4074b3720657c243bd66 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sun, 1 May 2022 22:25:37 +0100 Subject: [PATCH] Add IEnumerable.For and ForEach (#50) --- X10D.Tests/src/Core/EnumerableTests.cs | 64 ++++++++++++++++++ X10D/src/Collections/EnumerableExtensions.cs | 68 ++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/X10D.Tests/src/Core/EnumerableTests.cs b/X10D.Tests/src/Core/EnumerableTests.cs index 5b6deba..8e85c2f 100644 --- a/X10D.Tests/src/Core/EnumerableTests.cs +++ b/X10D.Tests/src/Core/EnumerableTests.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.Collections; using X10D.Core; namespace X10D.Tests.Core; @@ -17,4 +18,67 @@ public class EnumerableTests Assert.IsTrue(array.Count() == 1); Assert.AreEqual(o, array.ElementAt(0)); } + + [TestMethod] + public void For_ShouldTransform_GivenTransformationDelegate() + { + var oneToTen = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + var multipliedByIndex = new[] {0, 2, 6, 12, 20, 30, 42, 56, 72, 90}; + + IEnumerable source = oneToTen.Select(i => new DummyClass {Value = i}).ToArray(); + IEnumerable values = source.Select(o => o.Value); + CollectionAssert.AreEqual(oneToTen, values.ToArray()); + + source.For((i, o) => o.Value *= i); + values = source.Select(o => o.Value); + CollectionAssert.AreEqual(multipliedByIndex, values.ToArray()); + } + + [TestMethod] + public void For_ShouldThrow_GivenNullSource() + { + IEnumerable? source = null; + Assert.ThrowsException(() => source!.For((_, _) => { })); + } + + [TestMethod] + public void For_ShouldThrow_GivenNullAction() + { + IEnumerable source = ArraySegment.Empty; + Assert.ThrowsException(() => source.For(null!)); + } + + [TestMethod] + public void ForEach_ShouldTransform_GivenTransformationDelegate() + { + var oneToTen = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + var oneToTenDoubled = new[] {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; + + IEnumerable source = oneToTen.Select(i => new DummyClass {Value = i}).ToArray(); + IEnumerable values = source.Select(o => o.Value); + CollectionAssert.AreEqual(oneToTen, values.ToArray()); + + source.ForEach(o => o.Value *= 2); + values = source.Select(o => o.Value); + CollectionAssert.AreEqual(oneToTenDoubled, values.ToArray()); + } + + [TestMethod] + public void ForEach_ShouldThrow_GivenNullSource() + { + IEnumerable? source = null; + Assert.ThrowsException(() => source!.ForEach(_ => { })); + } + + [TestMethod] + public void ForEach_ShouldThrow_GivenNullAction() + { + IEnumerable source = ArraySegment.Empty; + Assert.ThrowsException(() => source.ForEach(null!)); + } + + private class DummyClass + { + public int Value { get; set; } + } } diff --git a/X10D/src/Collections/EnumerableExtensions.cs b/X10D/src/Collections/EnumerableExtensions.cs index baa8d19..2dfc589 100644 --- a/X10D/src/Collections/EnumerableExtensions.cs +++ b/X10D/src/Collections/EnumerableExtensions.cs @@ -7,6 +7,74 @@ namespace X10D.Collections; /// public static class EnumerableExtensions { + /// + /// Performs the specified action on each element of the . + /// + /// + /// The whose elements on which to perform . + /// + /// + /// The delegate to perform on each element of the . The + /// argument passed to this delegate represents the index. + /// + /// The type of the elements in . + /// + /// is . + /// -or- + /// is . + /// + public static void For(this IEnumerable source, Action action) + { + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (action is null) + { + throw new ArgumentNullException(nameof(action)); + } + + var index = 0; + foreach (T item in source) + { + action(index++, item); + } + } + + /// + /// Performs the specified action on each element of the . + /// + /// + /// The whose elements on which to perform . + /// + /// + /// The delegate to perform on each element of the . + /// + /// The type of the elements in . + /// + /// is . + /// -or- + /// is . + /// + public static void ForEach(this IEnumerable source, Action action) + { + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (action is null) + { + throw new ArgumentNullException(nameof(action)); + } + + foreach (T item in source) + { + action(item); + } + } + /// /// Reorganizes the elements in an enumerable by implementing a Fisher-Yates shuffle, and returns th shuffled result. ///