zip
parent
4d13523df7
commit
c0da316cb4
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
|
@ -8,12 +9,37 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
|
||||
public static IUniTaskAsyncEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second)
|
||||
{
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
|
||||
return Zip(first, second, (x, y) => (x, y));
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
|
||||
{
|
||||
return new Cysharp.Threading.Tasks.Linq.Zip<TFirst, TSecond, TResult>(first, second, resultSelector);
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
|
||||
|
||||
return new Zip<TFirst, TSecond, TResult>(first, second, resultSelector);
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TResult> ZipAwait<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> selector)
|
||||
{
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
Error.ThrowArgumentNullException(selector, nameof(selector));
|
||||
|
||||
return new ZipAwait<TFirst, TSecond, TResult>(first, second, selector);
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TResult> ZipAwaitWithCancellation<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> selector)
|
||||
{
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
Error.ThrowArgumentNullException(selector, nameof(selector));
|
||||
|
||||
return new ZipAwaitWithCancellation<TFirst, TSecond, TResult>(first, second, selector);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,30 +150,33 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.secondAwaiter.GetResult())
|
||||
if (self.TryGetResult(self.secondAwaiter, out var result))
|
||||
{
|
||||
try
|
||||
if (result)
|
||||
{
|
||||
self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
try
|
||||
{
|
||||
self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
|
||||
if (self.cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
if (self.cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(true);
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
|
@ -186,7 +215,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
{
|
||||
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
|
||||
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
|
||||
static readonly Action<object> unwrapResultTaskDelegate = UnwrapResultTask;
|
||||
static readonly Action<object> resultAwaitCoreDelegate = ResultAwaitCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TFirst> first;
|
||||
readonly IUniTaskAsyncEnumerable<TSecond> second;
|
||||
|
@ -239,67 +268,84 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.firstAwaiter.GetResult())
|
||||
if (self.TryGetResult(self.firstAwaiter, out var result))
|
||||
{
|
||||
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
|
||||
if (self.secondAwaiter.IsCompleted)
|
||||
if (result)
|
||||
{
|
||||
SecondMoveNextCore(self);
|
||||
try
|
||||
{
|
||||
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.secondAwaiter.IsCompleted)
|
||||
{
|
||||
SecondMoveNextCore(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void SecondMoveNextCore(object state)
|
||||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.secondAwaiter.GetResult())
|
||||
if (self.TryGetResult(self.secondAwaiter, out var result))
|
||||
{
|
||||
var task = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
|
||||
self.resultAwaiter = task.GetAwaiter();
|
||||
if (self.resultAwaiter.IsCompleted)
|
||||
if (result)
|
||||
{
|
||||
UnwrapResultTask(self);
|
||||
try
|
||||
{
|
||||
self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current).GetAwaiter();
|
||||
if (self.resultAwaiter.IsCompleted)
|
||||
{
|
||||
ResultAwaitCore(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.resultAwaiter.SourceOnCompleted(unwrapResultTaskDelegate, self);
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void UnwrapResultTask(object state)
|
||||
static void ResultAwaitCore(object state)
|
||||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
try
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = self.resultAwaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
self.Current = result;
|
||||
|
||||
if (self.cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(true);
|
||||
if (self.cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,4 +363,173 @@ namespace Cysharp.Threading.Tasks.Linq
|
|||
}
|
||||
}
|
||||
|
||||
internal sealed class ZipAwaitWithCancellation<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TFirst> first;
|
||||
readonly IUniTaskAsyncEnumerable<TSecond> second;
|
||||
readonly Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector;
|
||||
|
||||
public ZipAwaitWithCancellation(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector)
|
||||
{
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.resultSelector = resultSelector;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new Enumerator(first, second, resultSelector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
|
||||
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
|
||||
static readonly Action<object> resultAwaitCoreDelegate = ResultAwaitCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TFirst> first;
|
||||
readonly IUniTaskAsyncEnumerable<TSecond> second;
|
||||
readonly Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector;
|
||||
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
|
||||
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
|
||||
|
||||
UniTask<bool>.Awaiter firstAwaiter;
|
||||
UniTask<bool>.Awaiter secondAwaiter;
|
||||
UniTask<TResult>.Awaiter resultAwaiter;
|
||||
|
||||
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.resultSelector = resultSelector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
completionSource.Reset();
|
||||
|
||||
if (firstEnumerator == null)
|
||||
{
|
||||
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
|
||||
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
|
||||
}
|
||||
|
||||
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
|
||||
|
||||
if (firstAwaiter.IsCompleted)
|
||||
{
|
||||
FirstMoveNextCore(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
|
||||
}
|
||||
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
static void FirstMoveNextCore(object state)
|
||||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.TryGetResult(self.firstAwaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
try
|
||||
{
|
||||
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.secondAwaiter.IsCompleted)
|
||||
{
|
||||
SecondMoveNextCore(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SecondMoveNextCore(object state)
|
||||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.TryGetResult(self.secondAwaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
try
|
||||
{
|
||||
self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current, self.cancellationToken).GetAwaiter();
|
||||
if (self.resultAwaiter.IsCompleted)
|
||||
{
|
||||
ResultAwaitCore(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
self.completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResultAwaitCore(object state)
|
||||
{
|
||||
var self = (Enumerator)state;
|
||||
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
|
||||
if (self.cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
if (firstEnumerator != null)
|
||||
{
|
||||
await firstEnumerator.DisposeAsync();
|
||||
}
|
||||
if (secondEnumerator != null)
|
||||
{
|
||||
await secondEnumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -37,6 +37,58 @@ namespace NetCoreTests.Linq
|
|||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(9)]
|
||||
public async Task Select(int count)
|
||||
{
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select(x => x * x).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, count).Select(x => x * x).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
|
||||
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x) => UniTask.Run(() => x * x)).ToArrayAsync();
|
||||
zs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, count).Select((x, i) => x * x * i).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, count).Select((x, i) => x * x * i).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
|
||||
var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x, i) => UniTask.Run(() => x * x * i)).ToArrayAsync();
|
||||
zs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task SelectException()
|
||||
{
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.Select(x => UniTaskAsyncEnumerable.Range(0, 1)).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
|
||||
// await
|
||||
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.SelectAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
|
||||
// cancel
|
||||
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.SelectAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 9)] // empty + exists
|
||||
[InlineData(9, 0)] // exists + empty
|
||||
|
@ -44,69 +96,69 @@ namespace NetCoreTests.Linq
|
|||
public async Task SelectMany(int leftCount, int rightCount)
|
||||
{
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => x * y).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
|
||||
// await
|
||||
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
|
||||
// with cancel
|
||||
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray();
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
}
|
||||
|
@ -155,5 +207,70 @@ namespace NetCoreTests.Linq
|
|||
}
|
||||
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 9)] // empty + exists
|
||||
[InlineData(9, 0)] // exists + empty
|
||||
[InlineData(9, 9)] // same
|
||||
[InlineData(9, 4)] // leftlong
|
||||
[InlineData(4, 9)] // rightlong
|
||||
public async Task Zip(int leftCount, int rightCount)
|
||||
{
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).Zip(UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwait(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
{
|
||||
var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y, _) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray();
|
||||
xs.Should().BeEquivalentTo(ys);
|
||||
}
|
||||
}
|
||||
[Fact]
|
||||
public async Task ZipException()
|
||||
{
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.Zip(UniTaskAsyncEnumerable.Range(1, 10)).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = UniTaskAsyncEnumerable.Range(1, 10).Zip(item).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
|
||||
// a
|
||||
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.ZipAwait(UniTaskAsyncEnumerable.Range(1, 10), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = UniTaskAsyncEnumerable.Range(1, 10).ZipAwait(item, (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
|
||||
// c
|
||||
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = item.ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(1, 10), (x, y, c) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
foreach (var item in UniTaskTestException.Throws())
|
||||
{
|
||||
var xs = UniTaskAsyncEnumerable.Range(1, 10).ZipAwaitWithCancellation(item, (x, y, c) => UniTask.Run(() => (x, y))).ToArrayAsync();
|
||||
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue