diff --git a/CHANGELOG.md b/CHANGELOG.md index 63bb7db..fd3e06f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - X10D: Added `DateTime.GetIso8601WeekOfYear()` and `DateTimeOffset.GetIso8601WeekOfYear()` - X10D: Added `DirectoryInfo.Clear([bool])` - X10D: Added `IList.RemoveRange(Range)` +- X10D: Added `IList.Swap(IList)` (#62) - X10D: Added `Point.IsOnLine(LineF)`, `Point.IsOnLine(PointF, PointF)`, and `Point.IsOnLine(Vector2, Vector2)` - X10D: Added `PointF.IsOnLine(LineF)`, `PointF.IsOnLine(PointF, PointF)`, and `PointF.IsOnLine(Vector2, Vector2)` - X10D: Added `Point.ToSize()` diff --git a/X10D.Tests/src/Collections/ListTests.cs b/X10D.Tests/src/Collections/ListTests.cs index 87b9d20..dc6574a 100644 --- a/X10D.Tests/src/Collections/ListTests.cs +++ b/X10D.Tests/src/Collections/ListTests.cs @@ -154,4 +154,57 @@ public class ListTests { Assert.ThrowsException(() => ((List?)null)!.Shuffle()); } + + [TestMethod] + public void Swap_ShouldThrowArgumentNullException_GivenNullSource() + { + Assert.ThrowsException(() => ((IList?)null)!.Swap(new List())); + } + + [TestMethod] + public void Swap_ShouldThrowArgumentNullException_GivenNullTarget() + { + Assert.ThrowsException(() => new List().Swap(null!)); + } + + [TestMethod] + public void Swap_ShouldSwapElements_GivenMatchingElementCount() + { + var first = new List {1, 2, 3}; + var second = new List {4, 5, 6}; + + first.Swap(second); + + CollectionAssert.AreEqual(new[] {4, 5, 6}, first, string.Join(' ', first)); + CollectionAssert.AreEqual(new[] {1, 2, 3}, second, string.Join(' ', second)); + + first.Swap(second); + + CollectionAssert.AreEqual(new[] {1, 2, 3}, first, string.Join(' ', first)); + CollectionAssert.AreEqual(new[] {4, 5, 6}, second, string.Join(' ', second)); + } + + [TestMethod] + public void Swap_ShouldSwapElements_GivenDifferentElementCount() + { + var first = new List + { + 1, + 2, + 3, + 4, + 5 + }; + var second = new List {6, 7}; + + first.Swap(second); + + CollectionAssert.AreEqual(new[] {6, 7}, first, string.Join(' ', first)); + CollectionAssert.AreEqual(new[] {1, 2, 3, 4, 5}, second, string.Join(' ', second)); + + first.Swap(second); + + CollectionAssert.AreEqual(new[] {1, 2, 3, 4, 5}, first, string.Join(' ', first)); + CollectionAssert.AreEqual(new[] {6, 7}, second, string.Join(' ', second)); + } } diff --git a/X10D/src/Collections/ListExtensions.cs b/X10D/src/Collections/ListExtensions.cs index bd35d4b..87327b3 100644 --- a/X10D/src/Collections/ListExtensions.cs +++ b/X10D/src/Collections/ListExtensions.cs @@ -191,4 +191,56 @@ public static class ListExtensions (source[count], source[index]) = (source[index], source[count]); } } + + /// + /// Swaps all elements in a list with the elements in another list. + /// + /// The first list. + /// The second list. + /// The type of the elements in and . + /// + /// is . + /// -or- + /// is . + /// + public static void Swap(this IList source, IList other) + { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(other); +#else + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } + + if (other is null) + { + throw new ArgumentNullException(nameof(other)); + } +#endif + + int min = System.Math.Min(source.Count, other.Count); + for (var index = 0; index < min; index++) + { + (source[index], other[index]) = (other[index], source[index]); + } + + if (other.Count < source.Count) + { + for (int index = min; index < source.Count;) + { + other.Add(source[index]); + source.RemoveAt(index); + } + } + else if (source.Count < other.Count) + { + for (int index = min; index < other.Count;) + { + source.Add(other[index]); + other.RemoveAt(index); + } + } + } }