From 847af30945b1907655313587594f58d1208c7634 Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Thu, 13 Apr 2023 20:54:07 +0100 Subject: [PATCH 1/2] docs: properly document ArgumentNullException --- X10D/src/Collections/EnumerableExtensions.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/X10D/src/Collections/EnumerableExtensions.cs b/X10D/src/Collections/EnumerableExtensions.cs index 78707e1..c38e4df 100644 --- a/X10D/src/Collections/EnumerableExtensions.cs +++ b/X10D/src/Collections/EnumerableExtensions.cs @@ -349,7 +349,9 @@ public static class EnumerableExtensions /// /// An that contains elements from the input sequence that do not satisfy the condition. /// - /// or is null. + /// + /// or is . + /// [Pure] public static IEnumerable WhereNot(this IEnumerable source, Func predicate) { @@ -381,6 +383,7 @@ public static class EnumerableExtensions /// An that contains elements from the input sequence that are not /// ( in Visual Basic). /// + /// is . public static IEnumerable WhereNotNull(this IEnumerable source) { #if NET6_0_OR_GREATER From 0ae377250c6ffa565d388b9f547a5bbd2b2632ee Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Thu, 13 Apr 2023 20:55:24 +0100 Subject: [PATCH 2/2] feat: add IEnumerable.Except(T) LINQ-provided Except method filters by array, but there's no way to filter a single value. This method introduces single-value filtering. --- CHANGELOG.md | 3 ++- X10D.Tests/src/Linq/EnumerableTests.cs | 25 +++++++++++++++++++++++++ X10D/src/Linq/EnumerableExtensions.cs | 25 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 633397e..9482e2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - X10D: Added math-related extension methods for `BigInteger`. - X10D: Added `Span.Replace(T, T)`. - X10D: Added `CountDigits` for integer types. -- X10D: Added `Progress.OnProgressChanged([T])`; +- X10D: Added `IEnumerable.Except(T)`. +- X10D: Added `Progress.OnProgressChanged([T])`. - X10D: Added `TextWriter.WriteNoAlloc(int[, ReadOnlySpan[, IFormatProvider]])`. - X10D: Added `TextWriter.WriteNoAlloc(uint[, ReadOnlySpan[, IFormatProvider]])`. - X10D: Added `TextWriter.WriteNoAlloc(long[, ReadOnlySpan[, IFormatProvider]])`. diff --git a/X10D.Tests/src/Linq/EnumerableTests.cs b/X10D.Tests/src/Linq/EnumerableTests.cs index 6d0a2e4..c478578 100644 --- a/X10D.Tests/src/Linq/EnumerableTests.cs +++ b/X10D.Tests/src/Linq/EnumerableTests.cs @@ -37,6 +37,31 @@ public class EnumerableTests Assert.Throws(() => source!.ConcatOne("Foobar").ToArray()); } + [Test] + public void Except_ShouldFilterElements_GivenMatchingElements() + { + int[] source = Enumerable.Range(1, 10).ToArray(); + int[] result = source.Except(5).ToArray(); + + Assert.That(result, Is.EquivalentTo(new[] {1, 2, 3, 4, 6, 7, 8, 9, 10})); + } + + [Test] + public void Except_ShouldReturnSameElements_GivenNoMatchingElements() + { + int[] source = Enumerable.Range(1, 10).ToArray(); + int[] result = source.Except(11).ToArray(); + + Assert.That(result, Is.EquivalentTo(source)); + } + + [Test] + public void Except_ShouldThrowArgumentNullException_GivenNullSource() + { + IEnumerable source = null!; + Assert.Throws(() => source.Except(42)); + } + [Test] public void MinMax_ShouldReturnCorrectValues_UsingDefaultComparer() { diff --git a/X10D/src/Linq/EnumerableExtensions.cs b/X10D/src/Linq/EnumerableExtensions.cs index 4362dd2..92592bf 100644 --- a/X10D/src/Linq/EnumerableExtensions.cs +++ b/X10D/src/Linq/EnumerableExtensions.cs @@ -39,6 +39,31 @@ public static class EnumerableExtensions yield return value; } + /// + /// Filters a sequence of values by omitting elements that match a specified value. + /// + /// An to filter. + /// The value to omit. + /// The type of the elements of . + /// + /// An that contains elements from the input sequence that do not match the specified + /// value. + /// + /// is . + public static IEnumerable Except(this IEnumerable source, TSource item) + { +#if NET6_0_OR_GREATER + ArgumentNullException.ThrowIfNull(source); +#else + if (source is null) + { + throw new ArgumentNullException(nameof(source)); + } +#endif + + return source.Where(i => !Equals(i, item)); + } + /// /// Returns the minimum and maximum values in a sequence of values. ///