internal static async Task <LookupWithTask <TKey, TElement> > CreateAsync(IAsyncEnumerable <TElement> source, Func <TElement, CancellationToken, ValueTask <TKey> > keySelector, IEqualityComparer <TKey>?comparer, CancellationToken cancellationToken) { var lookup = new LookupWithTask <TKey, TElement>(comparer); await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) { var key = await keySelector(item, cancellationToken).ConfigureAwait(false); lookup.GetOrCreateGrouping(key).Add(item); } return(lookup); }
internal static async Task <LookupWithTask <TKey, TElement> > CreateForJoinAsync(IAsyncEnumerable <TElement> source, Func <TElement, CancellationToken, ValueTask <TKey> > keySelector, IEqualityComparer <TKey> comparer, CancellationToken cancellationToken) { var lookup = new LookupWithTask <TKey, TElement>(comparer); await foreach (var item in AsyncEnumerableExtensions.WithCancellation(source, cancellationToken).ConfigureAwait(false)) { var key = await keySelector(item, cancellationToken).ConfigureAwait(false); if (key != null) { lookup.GetGrouping(key, create: true).Add(item); } } return(lookup); }
internal static async Task <LookupWithTask <TKey, TElement> > CreateAsync <TSource>(IAsyncEnumerable <TSource> source, Func <TSource, CancellationToken, ValueTask <TKey> > keySelector, Func <TSource, CancellationToken, ValueTask <TElement> > elementSelector, IEqualityComparer <TKey> comparer, CancellationToken cancellationToken) { Debug.Assert(source != null); Debug.Assert(keySelector != null); Debug.Assert(elementSelector != null); var lookup = new LookupWithTask <TKey, TElement>(comparer); await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false)) { var key = await keySelector(item, cancellationToken).ConfigureAwait(false); var group = lookup.GetGrouping(key, create: true); var element = await elementSelector(item, cancellationToken).ConfigureAwait(false); group.Add(element); } return(lookup); }
public async ValueTask <bool> MoveNextAsync() { // nothing to do if (!await _outer.MoveNextAsync().ConfigureAwait(false)) { return(false); } if (_lookup == null) { _lookup = await Internal.LookupWithTask <TKey, TInner> .CreateForJoinAsync(_inner, _innerKeySelector, _comparer, _cancellationToken).ConfigureAwait(false); } var item = _outer.Current; var outerKey = await _outerKeySelector(item, _cancellationToken).ConfigureAwait(false); var inner = _lookup[outerKey].ToAsyncEnumerable(); Current = await _resultSelector(item, inner, _cancellationToken).ConfigureAwait(false); return(true); }
protected override async ValueTask <bool> MoveNextCore() { switch (_state) { case AsyncIteratorState.Allocated: _outerEnumerator = _outer.GetAsyncEnumerator(_cancellationToken); _mode = State_If; _state = AsyncIteratorState.Iterating; goto case AsyncIteratorState.Iterating; case AsyncIteratorState.Iterating: switch (_mode) { case State_If: if (await _outerEnumerator.MoveNextAsync().ConfigureAwait(false)) { _lookup = await Internal.LookupWithTask <TKey, TInner> .CreateForJoinAsync(_inner, _innerKeySelector, _comparer, _cancellationToken).ConfigureAwait(false); if (_lookup.Count != 0) { _mode = State_DoLoop; goto case State_DoLoop; } } break; case State_DoLoop: _item = _outerEnumerator.Current; var g = _lookup.GetGrouping(await _outerKeySelector(_item, _cancellationToken).ConfigureAwait(false), create: false); if (g != null) { _count = g._count; _elements = g._elements; _index = 0; _mode = State_For; goto case State_For; } // advance to while _mode = State_While; goto case State_While; case State_For: _current = await _resultSelector(_item, _elements[_index], _cancellationToken).ConfigureAwait(false); _index++; if (_index == _count) { _mode = State_While; } return(true); case State_While: var hasNext = await _outerEnumerator.MoveNextAsync().ConfigureAwait(false); if (hasNext) { goto case State_DoLoop; } break; } await DisposeAsync().ConfigureAwait(false); break; } return(false); }