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 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; } } } }