diff --git a/src/UniTask.NetCore/Linq/Aggregate.cs b/src/UniTask.NetCore/Linq/Aggregate.cs new file mode 100644 index 0000000..723a010 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Aggregate.cs @@ -0,0 +1,318 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + } + + internal static class Aggregate + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return resultSelector(value); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + // with async + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return await resultSelector(value); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + + // with cancellation + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return await resultSelector(value, cancellationToken); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ForEach.cs b/src/UniTask.NetCore/Linq/ForEach.cs index 956c319..600426c 100644 --- a/src/UniTask.NetCore/Linq/ForEach.cs +++ b/src/UniTask.NetCore/Linq/ForEach.cs @@ -11,7 +11,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); } public static UniTask ForEachAsync(this IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken = default) @@ -19,7 +19,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -27,7 +27,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -35,7 +35,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -43,7 +43,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -51,13 +51,13 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); } } - internal static class ForEach + internal static class ForEach { - public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -76,7 +76,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -96,7 +96,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -115,7 +115,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -135,7 +135,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -154,7 +154,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try diff --git a/src/UniTask.NetCore/Linq/_Aggregate.cs b/src/UniTask.NetCore/Linq/_Aggregate.cs deleted file mode 100644 index 388148b..0000000 --- a/src/UniTask.NetCore/Linq/_Aggregate.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class _Aggregate - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 902b263..6754ed8 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -21,50 +21,7 @@ namespace ___Dummy { // Buffer,Distinct, DistinctUntilChanged, Do, MaxBy, MinBy, Never,Return, Throw - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 18d9fc3..6ca3f92 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -34,13 +34,12 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - var xs = new[] { 1, 10, 100 }.GetEnumerator(); - while (xs.MoveNext()) - { + new int[] { }.Aggregate((x, y) => x + y); - } - Console.WriteLine(xs.MoveNext()); + + + await Task.Yield(); } diff --git a/src/UniTask.NetCoreTests/Linq/Aggregate.cs b/src/UniTask.NetCoreTests/Linq/Aggregate.cs index 146bc1a..61ac6f7 100644 --- a/src/UniTask.NetCoreTests/Linq/Aggregate.cs +++ b/src/UniTask.NetCoreTests/Linq/Aggregate.cs @@ -377,5 +377,120 @@ namespace NetCoreTests.Linq xs.Should().Be(ys); } } + + + [Fact] + public async Task AggregateTest1() + { + // 0 + await Assert.ThrowsAsync(async () => await new int[] { }.ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y)); + Assert.Throws(() => new int[] { }.Aggregate((x, y) => x + y)); + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 2).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 10).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + } + + [Fact] + public async Task AggregateTest2() + { + // 0 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 2).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 10).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + } + + [Fact] + public async Task AggregateTest3() + { + // 0 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 2).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 10).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + } + + [Fact] + public async Task ForEach() + { + var list = new List(); + await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().ForEachAsync(x => + { + list.Add(x); + }); + + list.Should().BeEquivalentTo(Enumerable.Range(1, 10)); + + var list2 = new List<(int, int)>(); + await Enumerable.Range(5, 10).ToUniTaskAsyncEnumerable().ForEachAsync((index, x) => + { + list2.Add((index, x)); + }); + + var list3 = Enumerable.Range(5, 10).Select((index, x) => (index, x)).ToArray(); + list2.Should().BeEquivalentTo(list3); + } } }