From 0d83283fcf97c53f3b7352f94974e51586dfaf92 Mon Sep 17 00:00:00 2001 From: Pavel Kalandra Date: Thu, 12 Oct 2023 17:06:02 +0200 Subject: [PATCH 1/5] Revert "Removed collection extensions that didn't crash on nulls." --- .../IEnumerableExtensionsBenchmarks.cs | 152 +++++++++--------- .../Collections/IsMultipleTests.cs | 80 ++++----- .../Collections/IsSingleTests.cs | 78 ++++----- .../Collections/SingleOptionTests.cs | 94 +++++------ .../IEnumerableExtensions_Generic.cs | 32 ++++ .../IEnumerableExtensions_Options.cs | 29 ++++ .../IEnumerableExtensions_ReadOnlyList.cs | 28 ++++ src/FuncSharp/FuncSharp.csproj | 4 +- src/FuncSharp/Try/TryExtensions.cs | 21 +-- 9 files changed, 304 insertions(+), 214 deletions(-) diff --git a/src/FuncSharp.Benchmarks/Collections/IEnumerableExtensionsBenchmarks.cs b/src/FuncSharp.Benchmarks/Collections/IEnumerableExtensionsBenchmarks.cs index ffc491d..974efeb 100644 --- a/src/FuncSharp.Benchmarks/Collections/IEnumerableExtensionsBenchmarks.cs +++ b/src/FuncSharp.Benchmarks/Collections/IEnumerableExtensionsBenchmarks.cs @@ -91,82 +91,82 @@ public void FirstOption() var x = StringEnumerable.FirstOption(); } - // // Last Result - 25.8.2023 - 14.6 ns - 40 B - // [Benchmark] - // public void SingleOption_Empty() - // { - // var x = StringStack_Empty.SingleOption(); - // } - // - // // Last Result - 25.8.2023 - 23.6 ns - 72 B - // [Benchmark] - // public void SingleOption_Single() - // { - // var x = StringStack_Single.SingleOption(); - // } - // - // // Last Result - 25.8.2023 - 22.0 ns - 40 B - // [Benchmark] - // public void SingleOption() - // { - // var x = StringStack_Many.SingleOption(); - // } - // - // // Last Result - 25.8.2023 - 1.4 ns - 0 B - // [Benchmark] - // public void IsMultiple_Stack() - // { - // var x = StringStack_Many.IsMultiple(); - // } - // - // // Last Result - 25.8.2023 - 53.8 ns - 144 B - // [Benchmark] - // public void IsMultiple_Enumerable() - // { - // var x = StringEnumerable.IsMultiple(); - // } - // - // // Last Result - 25.8.2023 - 6.9 ns - 0 B - // [Benchmark] - // public void IsMultiple_ArrayAsEnumerable() - // { - // var x = StringEnumerable_Array.IsMultiple(); - // } - // - // // Last Result - 25.8.2023 - 2.2 ns - 0 B - // [Benchmark] - // public void IsMultiple_Array() - // { - // var x = StringArray.IsMultiple(); - // } - // - // // Last Result - 25.8.2023 - 1.4 ns - 0 B - // [Benchmark] - // public void IsSingle_Stack() - // { - // var x = StringStack_Many.IsSingle(); - // } - // - // // Last Result - 25.8.2023 - 54.2 ns - 144 B - // [Benchmark] - // public void IsSingle_Enumerable() - // { - // var x = StringEnumerable.IsSingle(); - // } - // - // // Last Result - 25.8.2023 - 5.3 ns - 0 B - // [Benchmark] - // public void IsSingle_ArrayAsEnumerable() - // { - // var x = StringEnumerable_Array.IsSingle(); - // } - // - // // Last Result - 25.8.2023 - 2.2 ns - 0 B - // [Benchmark] - // public void IsSingle_Array() - // { - // var x = StringArray.IsSingle(); - // } + // Last Result - 25.8.2023 - 14.6 ns - 40 B + [Benchmark] + public void SingleOption_Empty() + { + var x = StringStack_Empty.SingleOption(); + } + + // Last Result - 25.8.2023 - 23.6 ns - 72 B + [Benchmark] + public void SingleOption_Single() + { + var x = StringStack_Single.SingleOption(); + } + + // Last Result - 25.8.2023 - 22.0 ns - 40 B + [Benchmark] + public void SingleOption() + { + var x = StringStack_Many.SingleOption(); + } + + // Last Result - 25.8.2023 - 1.4 ns - 0 B + [Benchmark] + public void IsMultiple_Stack() + { + var x = StringStack_Many.IsMultiple(); + } + + // Last Result - 25.8.2023 - 53.8 ns - 144 B + [Benchmark] + public void IsMultiple_Enumerable() + { + var x = StringEnumerable.IsMultiple(); + } + + // Last Result - 25.8.2023 - 6.9 ns - 0 B + [Benchmark] + public void IsMultiple_ArrayAsEnumerable() + { + var x = StringEnumerable_Array.IsMultiple(); + } + + // Last Result - 25.8.2023 - 2.2 ns - 0 B + [Benchmark] + public void IsMultiple_Array() + { + var x = StringArray.IsMultiple(); + } + + // Last Result - 25.8.2023 - 1.4 ns - 0 B + [Benchmark] + public void IsSingle_Stack() + { + var x = StringStack_Many.IsSingle(); + } + + // Last Result - 25.8.2023 - 54.2 ns - 144 B + [Benchmark] + public void IsSingle_Enumerable() + { + var x = StringEnumerable.IsSingle(); + } + + // Last Result - 25.8.2023 - 5.3 ns - 0 B + [Benchmark] + public void IsSingle_ArrayAsEnumerable() + { + var x = StringEnumerable_Array.IsSingle(); + } + + // Last Result - 25.8.2023 - 2.2 ns - 0 B + [Benchmark] + public void IsSingle_Array() + { + var x = StringArray.IsSingle(); + } // Last Result - 25.8.2023 - 121.5 ns - 416 B [Benchmark] diff --git a/src/FuncSharp.Tests/Collections/IsMultipleTests.cs b/src/FuncSharp.Tests/Collections/IsMultipleTests.cs index 89cb0a7..83ef7fc 100644 --- a/src/FuncSharp.Tests/Collections/IsMultipleTests.cs +++ b/src/FuncSharp.Tests/Collections/IsMultipleTests.cs @@ -6,44 +6,44 @@ namespace FuncSharp.Tests.Collections.INonEmptyEnumerable; public class IsMultipleTests { - // [Fact] - // public void IsMultiple_null() - // { - // IEnumerable enumerableNull = null; - // string[] arrayNull = null; - // - // Assert.False(enumerableNull.IsMultiple()); - // Assert.False(arrayNull.IsMultiple()); - // } - // - // [Fact] - // public void IsMultiple_Empty() - // { - // IEnumerable enumerableEmpty = Enumerable.Empty(); - // string[] arrayEmpty = new string[]{}; - // - // - // Assert.False(enumerableEmpty.IsMultiple()); - // Assert.False(arrayEmpty.IsMultiple()); - // } - // - // [Fact] - // public void IsMultiple_Single() - // { - // IEnumerable enumerableSingle = Enumerable.Repeat("A potato", 1); - // string[] arraySingle = new []{"A potato"}; - // - // Assert.False(enumerableSingle.IsMultiple()); - // Assert.False(arraySingle.IsMultiple()); - // } - // - // [Fact] - // public void IsMultiple_Multiple() - // { - // IEnumerable enumerableMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); - // string[] arrayMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); - // - // Assert.True(enumerableMultiple.IsMultiple()); - // Assert.True(arrayMultiple.IsMultiple()); - // } + [Fact] + public void IsMultiple_null() + { + IEnumerable enumerableNull = null; + string[] arrayNull = null; + + Assert.False(enumerableNull.IsMultiple()); + Assert.False(arrayNull.IsMultiple()); + } + + [Fact] + public void IsMultiple_Empty() + { + IEnumerable enumerableEmpty = Enumerable.Empty(); + string[] arrayEmpty = new string[]{}; + + + Assert.False(enumerableEmpty.IsMultiple()); + Assert.False(arrayEmpty.IsMultiple()); + } + + [Fact] + public void IsMultiple_Single() + { + IEnumerable enumerableSingle = Enumerable.Repeat("A potato", 1); + string[] arraySingle = new []{"A potato"}; + + Assert.False(enumerableSingle.IsMultiple()); + Assert.False(arraySingle.IsMultiple()); + } + + [Fact] + public void IsMultiple_Multiple() + { + IEnumerable enumerableMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); + string[] arrayMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); + + Assert.True(enumerableMultiple.IsMultiple()); + Assert.True(arrayMultiple.IsMultiple()); + } } \ No newline at end of file diff --git a/src/FuncSharp.Tests/Collections/IsSingleTests.cs b/src/FuncSharp.Tests/Collections/IsSingleTests.cs index 1ef652b..1c45d14 100644 --- a/src/FuncSharp.Tests/Collections/IsSingleTests.cs +++ b/src/FuncSharp.Tests/Collections/IsSingleTests.cs @@ -6,43 +6,43 @@ namespace FuncSharp.Tests.Collections.INonEmptyEnumerable; public class IsSingleTests { - // [Fact] - // public void IsSingle_null() - // { - // IEnumerable enumerableNull = null; - // string[] arrayNull = null; - // - // Assert.False(enumerableNull.IsSingle()); - // Assert.False(arrayNull.IsSingle()); - // } - // - // [Fact] - // public void IsSingle_Empty() - // { - // IEnumerable enumerableEmpty = Enumerable.Empty(); - // string[] arrayEmpty = new string[]{}; - // - // Assert.False(enumerableEmpty.IsSingle()); - // Assert.False(arrayEmpty.IsSingle()); - // } - // - // [Fact] - // public void IsSingle_Single() - // { - // IEnumerable enumerableSingle = Enumerable.Repeat("A potato", 1); - // string[] arraySingle = new []{"A potato"}; - // - // Assert.True(enumerableSingle.IsSingle()); - // Assert.True(arraySingle.IsSingle()); - // } - // - // [Fact] - // public void IsSingle_Multiple() - // { - // IEnumerable enumerableMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); - // string[] arrayMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); - // - // Assert.False(enumerableMultiple.IsSingle()); - // Assert.False(arrayMultiple.IsSingle()); - // } + [Fact] + public void IsSingle_null() + { + IEnumerable enumerableNull = null; + string[] arrayNull = null; + + Assert.False(enumerableNull.IsSingle()); + Assert.False(arrayNull.IsSingle()); + } + + [Fact] + public void IsSingle_Empty() + { + IEnumerable enumerableEmpty = Enumerable.Empty(); + string[] arrayEmpty = new string[]{}; + + Assert.False(enumerableEmpty.IsSingle()); + Assert.False(arrayEmpty.IsSingle()); + } + + [Fact] + public void IsSingle_Single() + { + IEnumerable enumerableSingle = Enumerable.Repeat("A potato", 1); + string[] arraySingle = new []{"A potato"}; + + Assert.True(enumerableSingle.IsSingle()); + Assert.True(arraySingle.IsSingle()); + } + + [Fact] + public void IsSingle_Multiple() + { + IEnumerable enumerableMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); + string[] arrayMultiple = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); + + Assert.False(enumerableMultiple.IsSingle()); + Assert.False(arrayMultiple.IsSingle()); + } } \ No newline at end of file diff --git a/src/FuncSharp.Tests/Collections/SingleOptionTests.cs b/src/FuncSharp.Tests/Collections/SingleOptionTests.cs index cd6fe33..76b5d43 100644 --- a/src/FuncSharp.Tests/Collections/SingleOptionTests.cs +++ b/src/FuncSharp.Tests/Collections/SingleOptionTests.cs @@ -6,51 +6,51 @@ namespace FuncSharp.Tests.Collections.INonEmptyEnumerable; public class SingleOptionTests { - // [Fact] - // public void SingleOption_Empty() - // { - // IEnumerable enumerable = Enumerable.Empty(); - // string[] array = new string[]{}; - // - // OptionAssert.IsEmpty(enumerable.SingleOption()); - // OptionAssert.IsEmpty(array.SingleOption()); - // - // OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("potato"))); - // OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("potato"))); - // } - // - // [Fact] - // public void SingleOption_Single() - // { - // IEnumerable enumerable = Enumerable.Repeat("A potato", 1); - // string[] array = new []{"A potato"}; - // - // OptionAssert.NonEmptyWithValue("A potato", enumerable.SingleOption()); - // OptionAssert.NonEmptyWithValue("A potato", array.SingleOption()); - // - // OptionAssert.NonEmptyWithValue("A potato", enumerable.SingleOption(t => t.Contains("potato"))); - // OptionAssert.NonEmptyWithValue("A potato", array.SingleOption(t => t.Contains("potato"))); - // - // OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("ASDF"))); - // OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("ASDF"))); - // } - // - // [Fact] - // public void SingleOption_Multiple() - // { - // IEnumerable enumerable = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); - // string[] array = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); - // - // OptionAssert.IsEmpty(enumerable.SingleOption()); - // OptionAssert.IsEmpty(array.SingleOption()); - // - // OptionAssert.NonEmptyWithValue("3 potatoes", enumerable.SingleOption(t => t.Contains("3 pot"))); - // OptionAssert.NonEmptyWithValue("3 potatoes", array.SingleOption(t => t.Contains("3 pot"))); - // - // OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("potato"))); - // OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("potato"))); - // - // OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("ASDF"))); - // OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("ASDF"))); - // } + [Fact] + public void SingleOption_Empty() + { + IEnumerable enumerable = Enumerable.Empty(); + string[] array = new string[]{}; + + OptionAssert.IsEmpty(enumerable.SingleOption()); + OptionAssert.IsEmpty(array.SingleOption()); + + OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("potato"))); + OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("potato"))); + } + + [Fact] + public void SingleOption_Single() + { + IEnumerable enumerable = Enumerable.Repeat("A potato", 1); + string[] array = new []{"A potato"}; + + OptionAssert.NonEmptyWithValue("A potato", enumerable.SingleOption()); + OptionAssert.NonEmptyWithValue("A potato", array.SingleOption()); + + OptionAssert.NonEmptyWithValue("A potato", enumerable.SingleOption(t => t.Contains("potato"))); + OptionAssert.NonEmptyWithValue("A potato", array.SingleOption(t => t.Contains("potato"))); + + OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("ASDF"))); + OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("ASDF"))); + } + + [Fact] + public void SingleOption_Multiple() + { + IEnumerable enumerable = Enumerable.Range(0, 10).Select(i => $"{i} potatoes"); + string[] array = Enumerable.Range(0, 10).Select(i => $"{i} potatoes").ToArray(); + + OptionAssert.IsEmpty(enumerable.SingleOption()); + OptionAssert.IsEmpty(array.SingleOption()); + + OptionAssert.NonEmptyWithValue("3 potatoes", enumerable.SingleOption(t => t.Contains("3 pot"))); + OptionAssert.NonEmptyWithValue("3 potatoes", array.SingleOption(t => t.Contains("3 pot"))); + + OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("potato"))); + OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("potato"))); + + OptionAssert.IsEmpty(enumerable.SingleOption(t => t.Contains("ASDF"))); + OptionAssert.IsEmpty(array.SingleOption(t => t.Contains("ASDF"))); + } } \ No newline at end of file diff --git a/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs b/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs index 34d002d..c6d75f9 100644 --- a/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs +++ b/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs @@ -101,6 +101,38 @@ public static IEnumerable ExceptNulls(this IEnumerable e) return e.Where(v => v is not null); } + public static bool IsMultiple(this IEnumerable e) + { + switch (e) + { + case null: + return false; + case IReadOnlyCollection c: + return c.Count > 1; + default: + { + using var enumerator = e.GetEnumerator(); + return enumerator.MoveNext() && enumerator.MoveNext(); + } + } + } + + public static bool IsSingle(this IEnumerable e) + { + switch (e) + { + case null: + return false; + case IReadOnlyCollection c1: + return c1.Count == 1; + default: + { + using var enumerator = e.GetEnumerator(); + return enumerator.MoveNext() && !enumerator.MoveNext(); + } + } + } + public static T Second(this IEnumerable e) { return e.ElementAt(1); diff --git a/src/FuncSharp/Collections/IEnumerableExtensions_Options.cs b/src/FuncSharp/Collections/IEnumerableExtensions_Options.cs index 8b16213..53a57de 100644 --- a/src/FuncSharp/Collections/IEnumerableExtensions_Options.cs +++ b/src/FuncSharp/Collections/IEnumerableExtensions_Options.cs @@ -76,4 +76,33 @@ public static Option LastOption(this IEnumerable source) return source.Reverse().FirstOption(); } + + /// + /// Returns the only value if the source contains just one value, otherwise an empty option. + /// + public static Option SingleOption(this IEnumerable source, Func predicate) + { + return source.Where(predicate).SingleOption(); + } + + /// + /// Returns the only value if the source contains just one value, otherwise an empty option. + /// + public static Option SingleOption(this IEnumerable source) + { + if (source is IReadOnlyList list) + { + return list.SingleOption(); + } + + using var enumerator = source.GetEnumerator(); + if (!enumerator.MoveNext()) + { + return Option.Empty(); + } + var result = enumerator.Current; + return enumerator.MoveNext() + ? Option.Empty() + : Option.Valued(result); + } } \ No newline at end of file diff --git a/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs b/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs index c5feb70..374b5f3 100644 --- a/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs +++ b/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs @@ -6,6 +6,34 @@ namespace FuncSharp; public static partial class IEnumerableExtensions { + [Pure] + public static bool IsMultiple(this IReadOnlyCollection collection) + { + return collection is not null && collection.Count > 1; + } + + [Pure] + public static bool IsSingle(this IReadOnlyCollection collection) + { + return collection is not null && collection.Count == 1; + } + + [Pure] + public static T Single(this IReadOnlyList list) + { + return list.IsSingle() + ? list[0] + : throw new ArgumentException("Source is not a single element."); + } + + [Pure] + public static Option SingleOption(this IReadOnlyList list) + { + return list.IsSingle() + ? Option.Valued(list[0]) + : Option.Empty(); + } + [Pure] public static T First(this IReadOnlyList list) { diff --git a/src/FuncSharp/FuncSharp.csproj b/src/FuncSharp/FuncSharp.csproj index 707afdd..73827eb 100644 --- a/src/FuncSharp/FuncSharp.csproj +++ b/src/FuncSharp/FuncSharp.csproj @@ -2,7 +2,7 @@ true CS1591 - 8.0.0-preview.3 + 8.0.0-preview.2 8.0.0 8.0.0 FuncSharp @@ -13,7 +13,7 @@ https://github.com/MewsSystems/FuncSharp MIT false - Removed more collection methods that were handling nulls so that we can update the usages in Mews and bring it back. + Introduced more numeric types and helpers for working with collections of tuples, tries and coproducts. git https://github.com/MewsSystems/FuncSharp true diff --git a/src/FuncSharp/Try/TryExtensions.cs b/src/FuncSharp/Try/TryExtensions.cs index 82fb202..8604306 100644 --- a/src/FuncSharp/Try/TryExtensions.cs +++ b/src/FuncSharp/Try/TryExtensions.cs @@ -113,15 +113,16 @@ public static A Get(this Try t) public static T Get(this Try> value) where E : Exception { - if (value.IsSuccess) - return value.Success.Value; - - var exceptions = value.Error.Value; - if (exceptions.Count == 1) - { - ExceptionDispatchInfo.Capture(exceptions[0]).Throw(); - } - - throw new AggregateException(exceptions); + return value.Match( + s => s, + (Func, T>)(e => + { + if (e.IsSingle()) + { + ExceptionDispatchInfo.Capture(e[0]).Throw(); + } + throw new AggregateException(e); + }) + ); } } \ No newline at end of file From 3ce5393f1fb5b5600e78a13db05bf956903df117 Mon Sep 17 00:00:00 2001 From: KaliCZ Date: Thu, 12 Oct 2023 17:14:29 +0200 Subject: [PATCH 2/5] Also bumped the package version. --- src/FuncSharp/FuncSharp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FuncSharp/FuncSharp.csproj b/src/FuncSharp/FuncSharp.csproj index 73827eb..3b4f82f 100644 --- a/src/FuncSharp/FuncSharp.csproj +++ b/src/FuncSharp/FuncSharp.csproj @@ -2,7 +2,7 @@ true CS1591 - 8.0.0-preview.2 + 8.0.0 8.0.0 8.0.0 FuncSharp @@ -13,7 +13,7 @@ https://github.com/MewsSystems/FuncSharp MIT false - Introduced more numeric types and helpers for working with collections of tuples, tries and coproducts. + Mews methods on collections now crash when the collection is null. Just like LINQ does. Added methods for better working with collections of coproducts, tries and tuples. Added a more performant Match overload for working with IEquatable. git https://github.com/MewsSystems/FuncSharp true From 579bc1e0e7db55698584f1c50b8b569e409e486c Mon Sep 17 00:00:00 2001 From: KaliCZ Date: Thu, 12 Oct 2023 17:32:43 +0200 Subject: [PATCH 3/5] Finalized implementation. --- .../Collections/IEnumerableExtensions_Generic.cs | 4 ---- .../Collections/IEnumerableExtensions_ReadOnlyList.cs | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs b/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs index c6d75f9..bdac070 100644 --- a/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs +++ b/src/FuncSharp/Collections/IEnumerableExtensions_Generic.cs @@ -105,8 +105,6 @@ public static bool IsMultiple(this IEnumerable e) { switch (e) { - case null: - return false; case IReadOnlyCollection c: return c.Count > 1; default: @@ -121,8 +119,6 @@ public static bool IsSingle(this IEnumerable e) { switch (e) { - case null: - return false; case IReadOnlyCollection c1: return c1.Count == 1; default: diff --git a/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs b/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs index 374b5f3..15b80f9 100644 --- a/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs +++ b/src/FuncSharp/Collections/IEnumerableExtensions_ReadOnlyList.cs @@ -9,19 +9,19 @@ public static partial class IEnumerableExtensions [Pure] public static bool IsMultiple(this IReadOnlyCollection collection) { - return collection is not null && collection.Count > 1; + return collection.Count > 1; } [Pure] public static bool IsSingle(this IReadOnlyCollection collection) { - return collection is not null && collection.Count == 1; + return collection.Count == 1; } [Pure] public static T Single(this IReadOnlyList list) { - return list.IsSingle() + return list.Count == 1 ? list[0] : throw new ArgumentException("Source is not a single element."); } @@ -29,7 +29,7 @@ public static T Single(this IReadOnlyList list) [Pure] public static Option SingleOption(this IReadOnlyList list) { - return list.IsSingle() + return list.Count == 1 ? Option.Valued(list[0]) : Option.Empty(); } From c7dd93570acaa45a7dc969067ae232567fea8be4 Mon Sep 17 00:00:00 2001 From: KaliCZ Date: Thu, 12 Oct 2023 17:34:18 +0200 Subject: [PATCH 4/5] Removed tests for null collections --- src/FuncSharp.Tests/Collections/IsMultipleTests.cs | 10 ---------- src/FuncSharp.Tests/Collections/IsSingleTests.cs | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/src/FuncSharp.Tests/Collections/IsMultipleTests.cs b/src/FuncSharp.Tests/Collections/IsMultipleTests.cs index 83ef7fc..e16e325 100644 --- a/src/FuncSharp.Tests/Collections/IsMultipleTests.cs +++ b/src/FuncSharp.Tests/Collections/IsMultipleTests.cs @@ -6,16 +6,6 @@ namespace FuncSharp.Tests.Collections.INonEmptyEnumerable; public class IsMultipleTests { - [Fact] - public void IsMultiple_null() - { - IEnumerable enumerableNull = null; - string[] arrayNull = null; - - Assert.False(enumerableNull.IsMultiple()); - Assert.False(arrayNull.IsMultiple()); - } - [Fact] public void IsMultiple_Empty() { diff --git a/src/FuncSharp.Tests/Collections/IsSingleTests.cs b/src/FuncSharp.Tests/Collections/IsSingleTests.cs index 1c45d14..e43444d 100644 --- a/src/FuncSharp.Tests/Collections/IsSingleTests.cs +++ b/src/FuncSharp.Tests/Collections/IsSingleTests.cs @@ -6,16 +6,6 @@ namespace FuncSharp.Tests.Collections.INonEmptyEnumerable; public class IsSingleTests { - [Fact] - public void IsSingle_null() - { - IEnumerable enumerableNull = null; - string[] arrayNull = null; - - Assert.False(enumerableNull.IsSingle()); - Assert.False(arrayNull.IsSingle()); - } - [Fact] public void IsSingle_Empty() { From 13f996c07f90451acaebaf768ed0ff2c0cdd8378 Mon Sep 17 00:00:00 2001 From: KaliCZ Date: Thu, 12 Oct 2023 17:46:17 +0200 Subject: [PATCH 5/5] revert of unwanted changes. --- src/FuncSharp/Try/TryExtensions.cs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/FuncSharp/Try/TryExtensions.cs b/src/FuncSharp/Try/TryExtensions.cs index 8604306..82fb202 100644 --- a/src/FuncSharp/Try/TryExtensions.cs +++ b/src/FuncSharp/Try/TryExtensions.cs @@ -113,16 +113,15 @@ public static A Get(this Try t) public static T Get(this Try> value) where E : Exception { - return value.Match( - s => s, - (Func, T>)(e => - { - if (e.IsSingle()) - { - ExceptionDispatchInfo.Capture(e[0]).Throw(); - } - throw new AggregateException(e); - }) - ); + if (value.IsSuccess) + return value.Success.Value; + + var exceptions = value.Error.Value; + if (exceptions.Count == 1) + { + ExceptionDispatchInfo.Capture(exceptions[0]).Throw(); + } + + throw new AggregateException(exceptions); } } \ No newline at end of file