From b20b37e7a5b39d389b3d1187d42239a211f4407a Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 15:53:27 +0900 Subject: [PATCH] Distinct, Except, Intersect, Union --- .../Linq/AsyncEnumeratorBase.cs | 10 +- src/UniTask.NetCore/Linq/Distinct.cs | 843 ++--------------- src/UniTask.NetCore/Linq/Except.cs | 883 +++-------------- src/UniTask.NetCore/Linq/Intersect.cs | 884 +++--------------- src/UniTask.NetCore/Linq/Join.cs | 776 +-------------- src/UniTask.NetCore/Linq/ToHashSet.cs | 14 +- src/UniTask.NetCore/Linq/Union.cs | 795 +--------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 47 - src/UniTask.NetCoreSandbox/Program.cs | 2 +- src/UniTask.NetCoreTests/Linq/Sets.cs | 138 +++ src/UniTask/Assets/Plugins/UniTask/UniTask.cs | 5 + 11 files changed, 485 insertions(+), 3912 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/Sets.cs diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index d5e5b4f..b4b4493 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -100,10 +100,18 @@ namespace Cysharp.Threading.Tasks.Linq } completionSource.Reset(); - SourceMoveNext(); + if (!OnFirstIteration()) + { + SourceMoveNext(); + } return new UniTask(this, completionSource.Version); } + protected virtual bool OnFirstIteration() + { + return false; + } + protected void SourceMoveNext() { CONTINUE: diff --git a/src/UniTask.NetCore/Linq/Distinct.cs b/src/UniTask.NetCore/Linq/Distinct.cs index 980cae0..fc4aa48 100644 --- a/src/UniTask.NetCore/Linq/Distinct.cs +++ b/src/UniTask.NetCore/Linq/Distinct.cs @@ -1,775 +1,76 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Distinct + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Distinct(source, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Distinct(source, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Distinct : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly IEqualityComparer comparer; + + public Distinct(IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + this.source = source; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly HashSet set; + + public Enumerator(IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.set = new HashSet(comparer); + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + if (set.Add(v)) + { + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Except.cs b/src/UniTask.NetCore/Linq/Except.cs index db2aa41..28e565a 100644 --- a/src/UniTask.NetCore/Linq/Except.cs +++ b/src/UniTask.NetCore/Linq/Except.cs @@ -1,775 +1,116 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Except + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return new Except(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Except(first, second, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Except : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly IEqualityComparer comparer; + + public Except(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + this.first = first; + this.second = second; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + static Action HashSetAsyncCoreDelegate = HashSetAsyncCore; + + readonly IEqualityComparer comparer; + readonly IUniTaskAsyncEnumerable second; + + HashSet set; + UniTask>.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(first, cancellationToken) + { + this.second = second; + this.comparer = comparer; + } + + protected override bool OnFirstIteration() + { + if (set != null) return false; + + awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter(); + if (awaiter.IsCompleted) + { + set = awaiter.GetResult(); + SourceMoveNext(); + } + else + { + awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this); + } + + return true; + } + + static void HashSetAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.set = result; + self.SourceMoveNext(); + } + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + if (set.Add(v)) + { + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Intersect.cs b/src/UniTask.NetCore/Linq/Intersect.cs index 4207678..897caa1 100644 --- a/src/UniTask.NetCore/Linq/Intersect.cs +++ b/src/UniTask.NetCore/Linq/Intersect.cs @@ -1,775 +1,117 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Intersect + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return new Intersect(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Intersect(first, second, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Intersect : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly IEqualityComparer comparer; + + public Intersect(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + this.first = first; + this.second = second; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + static Action HashSetAsyncCoreDelegate = HashSetAsyncCore; + + readonly IEqualityComparer comparer; + readonly IUniTaskAsyncEnumerable second; + + HashSet set; + UniTask>.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(first, cancellationToken) + { + this.second = second; + this.comparer = comparer; + } + + protected override bool OnFirstIteration() + { + if (set != null) return false; + + awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter(); + if (awaiter.IsCompleted) + { + set = awaiter.GetResult(); + SourceMoveNext(); + } + else + { + awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this); + } + + return true; + } + + static void HashSetAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.set = result; + self.SourceMoveNext(); + } + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + + if (set.Remove(v)) + { + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs index 1b1aa09..5f28270 100644 --- a/src/UniTask.NetCore/Linq/Join.cs +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -1,775 +1 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class Join - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToHashSet.cs b/src/UniTask.NetCore/Linq/ToHashSet.cs index d858db1..ec54841 100644 --- a/src/UniTask.NetCore/Linq/ToHashSet.cs +++ b/src/UniTask.NetCore/Linq/ToHashSet.cs @@ -10,15 +10,23 @@ namespace Cysharp.Threading.Tasks.Linq { Error.ThrowArgumentNullException(source, nameof(source)); - return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, comparer, cancellationToken); } } internal static class ToHashSet { - internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken) { - var set = new HashSet(); + var set = new HashSet(comparer); var e = source.GetAsyncEnumerator(cancellationToken); try diff --git a/src/UniTask.NetCore/Linq/Union.cs b/src/UniTask.NetCore/Linq/Union.cs index 3413223..2ceefab 100644 --- a/src/UniTask.NetCore/Linq/Union.cs +++ b/src/UniTask.NetCore/Linq/Union.cs @@ -1,775 +1,26 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System.Collections.Generic; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Union + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return Union(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + // improv without combinate? + return first.Concat(second).Distinct(comparer); + } } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 7fca4f5..96f13ab 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -26,26 +26,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - - public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } @@ -200,16 +180,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { throw new NotImplementedException(); @@ -309,10 +279,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) - { - throw new NotImplementedException(); - } public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) { @@ -380,19 +346,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - - - } diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 52a62d1..f9deafb 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -54,7 +54,7 @@ namespace NetCoreSandbox - + //Enumerable.Range(1,10).ToHashSet( } diff --git a/src/UniTask.NetCoreTests/Linq/Sets.cs b/src/UniTask.NetCoreTests/Linq/Sets.cs new file mode 100644 index 0000000..627c578 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Sets.cs @@ -0,0 +1,138 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Sets + { + public static IEnumerable array1 = new object[][] + { + new object[] { new int[] { } }, // empty + new object[] { new int[] { 1, 2, 3 } }, // no dup + new object[] { new int[] { 1, 2, 3, 3, 4, 5, 2 } }, // dup + }; + + public static IEnumerable array2 = new object[][] + { + new object[] { new int[] { } }, // empty + new object[] { new int[] { 1, 2 } }, + new object[] { new int[] { 1, 2, 4, 5, 9 } }, // dup + }; + + [Theory] + [MemberData(nameof(array1))] + public async Task Distinct(int[] array) + { + var xs = await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync(); + var ys = array.Distinct().ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task DistinctThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Distinct().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Except() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Except(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Except(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task ExceptThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Except(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Except(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Intersect() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Intersect(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Intersect(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task IntersectThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Intersect(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Intersect(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Union() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Union(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Union(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task UnionThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Union(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Union(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } +} diff --git a/src/UniTask/Assets/Plugins/UniTask/UniTask.cs b/src/UniTask/Assets/Plugins/UniTask/UniTask.cs index 1958d3e..35bf8b6 100644 --- a/src/UniTask/Assets/Plugins/UniTask/UniTask.cs +++ b/src/UniTask/Assets/Plugins/UniTask/UniTask.cs @@ -15,6 +15,7 @@ namespace Cysharp.Threading.Tasks { internal static readonly Action InvokeActionDelegate = InvokeAction; + [DebuggerHidden] static void InvokeAction(object state) { ((Action)state).Invoke(); @@ -318,6 +319,8 @@ namespace Cysharp.Threading.Tasks /// /// If register manually continuation, you can use it instead of for compiler OnCompleted methods. /// + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SourceOnCompleted(Action continuation, object state) { if (task.source == null) @@ -640,6 +643,8 @@ namespace Cysharp.Threading.Tasks /// /// If register manually continuation, you can use it instead of for compiler OnCompleted methods. /// + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SourceOnCompleted(Action continuation, object state) { var s = task.source;