From 636e2d03c0f5049f7088793b3a91e52c4e54e6ca Mon Sep 17 00:00:00 2001 From: Elianora Rose Date: Mon, 1 Apr 2024 14:01:23 -0400 Subject: [PATCH] Add TrySingle overloads for (#643) --- .../PublicAPI/net6.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net7.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 1 + .../netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + Source/SuperLinq.Async/TrySingle.cs | 41 ++++++++++++++- .../PublicAPI/net6.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net7.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net8.0/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net9.0/PublicAPI.Unshipped.txt | 1 + .../netcoreapp3.1/PublicAPI.Unshipped.txt | 1 + Source/SuperLinq/TrySingle.cs | 40 ++++++++++++++- Tests/SuperLinq.Async.Test/TrySingleTest.cs | 13 ++++- Tests/SuperLinq.Test/TrySingleTest.cs | 51 ++++++++++++++++++- 14 files changed, 151 insertions(+), 4 deletions(-) diff --git a/Source/SuperLinq.Async/PublicAPI/net6.0/PublicAPI.Unshipped.txt b/Source/SuperLinq.Async/PublicAPI/net6.0/PublicAPI.Unshipped.txt index 03ca905da..d251e1f35 100644 --- a/Source/SuperLinq.Async/PublicAPI/net6.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq.Async/PublicAPI/net6.0/PublicAPI.Unshipped.txt @@ -104,4 +104,5 @@ static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collectio static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IAsyncEnumerable!>! +static SuperLinq.Async.AsyncSuperEnumerable.TrySingle(this System.Collections.Generic.IAsyncEnumerable! source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask SuperLinq.Async.IAsyncBuffer.ConfigureAwait(bool continueOnCapturedContext) -> System.Runtime.CompilerServices.ConfiguredAsyncDisposable diff --git a/Source/SuperLinq.Async/PublicAPI/net7.0/PublicAPI.Unshipped.txt b/Source/SuperLinq.Async/PublicAPI/net7.0/PublicAPI.Unshipped.txt index 03ca905da..d251e1f35 100644 --- a/Source/SuperLinq.Async/PublicAPI/net7.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq.Async/PublicAPI/net7.0/PublicAPI.Unshipped.txt @@ -104,4 +104,5 @@ static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collectio static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IAsyncEnumerable!>! +static SuperLinq.Async.AsyncSuperEnumerable.TrySingle(this System.Collections.Generic.IAsyncEnumerable! source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask SuperLinq.Async.IAsyncBuffer.ConfigureAwait(bool continueOnCapturedContext) -> System.Runtime.CompilerServices.ConfiguredAsyncDisposable diff --git a/Source/SuperLinq.Async/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/Source/SuperLinq.Async/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 03ca905da..d251e1f35 100644 --- a/Source/SuperLinq.Async/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq.Async/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -104,4 +104,5 @@ static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collectio static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IAsyncEnumerable!>! +static SuperLinq.Async.AsyncSuperEnumerable.TrySingle(this System.Collections.Generic.IAsyncEnumerable! source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask SuperLinq.Async.IAsyncBuffer.ConfigureAwait(bool continueOnCapturedContext) -> System.Runtime.CompilerServices.ConfiguredAsyncDisposable diff --git a/Source/SuperLinq.Async/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/Source/SuperLinq.Async/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 03ca905da..d251e1f35 100644 --- a/Source/SuperLinq.Async/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq.Async/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -104,4 +104,5 @@ static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collectio static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IAsyncEnumerable!>! +static SuperLinq.Async.AsyncSuperEnumerable.TrySingle(this System.Collections.Generic.IAsyncEnumerable! source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask SuperLinq.Async.IAsyncBuffer.ConfigureAwait(bool continueOnCapturedContext) -> System.Runtime.CompilerServices.ConfiguredAsyncDisposable diff --git a/Source/SuperLinq.Async/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt b/Source/SuperLinq.Async/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt index 03ca905da..d251e1f35 100644 --- a/Source/SuperLinq.Async/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq.Async/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -104,4 +104,5 @@ static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collectio static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IAsyncEnumerable!>! static SuperLinq.Async.AsyncSuperEnumerable.Split(this System.Collections.Generic.IAsyncEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IAsyncEnumerable!>! +static SuperLinq.Async.AsyncSuperEnumerable.TrySingle(this System.Collections.Generic.IAsyncEnumerable! source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.ValueTask SuperLinq.Async.IAsyncBuffer.ConfigureAwait(bool continueOnCapturedContext) -> System.Runtime.CompilerServices.ConfiguredAsyncDisposable diff --git a/Source/SuperLinq.Async/TrySingle.cs b/Source/SuperLinq.Async/TrySingle.cs index 1b28a9f44..3756767b6 100644 --- a/Source/SuperLinq.Async/TrySingle.cs +++ b/Source/SuperLinq.Async/TrySingle.cs @@ -1,4 +1,4 @@ -namespace SuperLinq.Async; +namespace SuperLinq.Async; public static partial class AsyncSuperEnumerable { @@ -107,4 +107,43 @@ static async ValueTask Core( : resultSelector(many, default); } } + + /// + /// Returns the single element in the sequence if it contains exactly one element. + /// Similar to . + /// + /// + /// The type of the elements of . + /// + /// + /// The source sequence. + /// + /// + /// The optional cancellation token to be used for cancelling the sequence at any time. + /// + /// + /// The single element or the default value of . + /// + public static ValueTask TrySingle( + this IAsyncEnumerable source, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + return Core(source, cancellationToken); + + static async ValueTask Core( + IAsyncEnumerable source, + CancellationToken cancellationToken) + { + await using var e = source.GetConfiguredAsyncEnumerator(cancellationToken); + if (!await e.MoveNextAsync()) + return default; + + var current = e.Current; + return !await e.MoveNextAsync() + ? current + : default; + } + } } diff --git a/Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt b/Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt index 8ac07beb0..354235808 100644 --- a/Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq/PublicAPI/net6.0/PublicAPI.Unshipped.txt @@ -137,6 +137,7 @@ static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic. static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IEnumerable!>! +static SuperLinq.SuperEnumerable.TrySingle(this System.Collections.Generic.IEnumerable! source) -> TSource? static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! diff --git a/Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt b/Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt index 8ac07beb0..354235808 100644 --- a/Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq/PublicAPI/net7.0/PublicAPI.Unshipped.txt @@ -137,6 +137,7 @@ static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic. static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IEnumerable!>! +static SuperLinq.SuperEnumerable.TrySingle(this System.Collections.Generic.IEnumerable! source) -> TSource? static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! diff --git a/Source/SuperLinq/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/Source/SuperLinq/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 8ac07beb0..354235808 100644 --- a/Source/SuperLinq/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -137,6 +137,7 @@ static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic. static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IEnumerable!>! +static SuperLinq.SuperEnumerable.TrySingle(this System.Collections.Generic.IEnumerable! source) -> TSource? static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! diff --git a/Source/SuperLinq/PublicAPI/net9.0/PublicAPI.Unshipped.txt b/Source/SuperLinq/PublicAPI/net9.0/PublicAPI.Unshipped.txt index 67f546732..f085ecd88 100644 --- a/Source/SuperLinq/PublicAPI/net9.0/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq/PublicAPI/net9.0/PublicAPI.Unshipped.txt @@ -137,6 +137,7 @@ static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic. static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IEnumerable!>! +static SuperLinq.SuperEnumerable.TrySingle(this System.Collections.Generic.IEnumerable! source) -> TSource? static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! diff --git a/Source/SuperLinq/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt b/Source/SuperLinq/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt index 8ac07beb0..354235808 100644 --- a/Source/SuperLinq/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt +++ b/Source/SuperLinq/PublicAPI/netcoreapp3.1/PublicAPI.Unshipped.txt @@ -137,6 +137,7 @@ static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic. static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, int count) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer) -> System.Collections.Generic.IEnumerable!>! static SuperLinq.SuperEnumerable.Split(this System.Collections.Generic.IEnumerable! source, TSource separator, System.Collections.Generic.IEqualityComparer? comparer, int count) -> System.Collections.Generic.IEnumerable!>! +static SuperLinq.SuperEnumerable.TrySingle(this System.Collections.Generic.IEnumerable! source) -> TSource? static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, int size, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! static SuperLinq.SuperEnumerable.Window(this System.Collections.Generic.IEnumerable! source, TSource[]! array, SuperLinq.SuperEnumerable.ReadOnlySpanFunc! selector) -> System.Collections.Generic.IEnumerable! diff --git a/Source/SuperLinq/TrySingle.cs b/Source/SuperLinq/TrySingle.cs index 3474e8afa..fad730030 100644 --- a/Source/SuperLinq/TrySingle.cs +++ b/Source/SuperLinq/TrySingle.cs @@ -1,4 +1,4 @@ -namespace SuperLinq; +namespace SuperLinq; public static partial class SuperEnumerable { @@ -112,4 +112,42 @@ public static TResult TrySingle( : resultSelector(many, default); } } + + /// + /// Returns the single element in the sequence if it contains exactly one element. + /// Similar to . + /// + /// + /// The type of the elements of . + /// + /// + /// The source sequence. + /// + /// + /// The single element or the default value of . + /// + public static TSource? TrySingle(this IEnumerable source) + { + ArgumentNullException.ThrowIfNull(source); + + if (source.TryGetCollectionCount() is int n) + { + return n switch + { + 1 => source.First(), + 0 or _ => default + }; + } + else + { + using var e = source.GetEnumerator(); + if (!e.MoveNext()) + return default; + + var current = e.Current; + return !e.MoveNext() + ? current + : default; + } + } } diff --git a/Tests/SuperLinq.Async.Test/TrySingleTest.cs b/Tests/SuperLinq.Async.Test/TrySingleTest.cs index 7681fc2b8..0341ee2ad 100644 --- a/Tests/SuperLinq.Async.Test/TrySingleTest.cs +++ b/Tests/SuperLinq.Async.Test/TrySingleTest.cs @@ -1,4 +1,4 @@ -namespace Test.Async; +namespace Test.Async; public class TrySingleTest { @@ -61,4 +61,15 @@ public async Task TrySingleEnumeratesOnceOnlyAndDisposes(int numberOfElements, s var (cardinality, _) = await seq.TrySingle("zero", "one", "many"); Assert.Equal(expectedCardinality, cardinality); } + + [Theory] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(2, 0)] + public async Task TrySingleShouldReturnDefaultOrSingleValue(int numberOfElements, int expectedResult) + { + await using var seq = AsyncEnumerable.Range(1, numberOfElements).AsTestingSequence(); + var result = await seq.TrySingle(); + Assert.Equal(expectedResult, result); + } } diff --git a/Tests/SuperLinq.Test/TrySingleTest.cs b/Tests/SuperLinq.Test/TrySingleTest.cs index a94693ff6..3d948319d 100644 --- a/Tests/SuperLinq.Test/TrySingleTest.cs +++ b/Tests/SuperLinq.Test/TrySingleTest.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; namespace Test; @@ -110,4 +110,53 @@ public void TrySingleEnumeratesOnceOnlyAndDisposes(int numberOfElements, string var (cardinality, _) = seq.TrySingle("zero", "one", "many"); Assert.Equal(expectedCardinality, cardinality); } + + [Theory] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(2, 0)] + public void TrySingleShouldReturnDefaultOrSingleValue(int numberOfElements, int expectedResult) + { + using var seq = Enumerable.Range(1, numberOfElements).AsTestingSequence(); + var result = seq.TrySingle(); + Assert.Equal(expectedResult, result); + } + + public static IEnumerable GetListOfSequences(IEnumerable seq) => + seq.Select(x => (int?)x) + .GetListSequences() + .Select(x => new object[] { x }); + + [Theory] + [MemberData(nameof(GetListOfSequences), new int[] { })] + public void TrySingleShouldReturnWhenProvidedEmptyList(IDisposableEnumerable seq) + { + using (seq) + { + var value = seq.TrySingle(); + Assert.Null(value); + } + } + + [Theory] + [MemberData(nameof(GetListOfSequences), new int[] { 1, 2 })] + public void TrySingleShouldReturnWhenProvidedLongerList(IDisposableEnumerable seq) + { + using (seq) + { + var value = seq.TrySingle(); + Assert.Null(value); + } + } + + [Theory] + [MemberData(nameof(GetListOfSequences), new int[] { 1 })] + public void TrySingleShouldReturnWhenProvidedListWithSingleItem(IDisposableEnumerable seq) + { + using (seq) + { + var value = seq.TrySingle(); + Assert.Equal(1, value); + } + } }