private static async Task <T> FirstAsync <T>(IAsyncEnumerable <T> source, Boolean throwIfNone) { T retVal; var enumerator = source.GetAsyncEnumerator(); try { var success = await enumerator.WaitForNextAsync(); retVal = success ? enumerator.TryGetNext(out success) : default; if (!success) { if (throwIfNone) { throw AsyncProviderUtilities.EmptySequenceException(); } else { retVal = default; } } } finally { await enumerator.DisposeAsync(); } return(retVal); }
/// <summary> /// Similarly to <see cref="System.Linq.Enumerable.Aggregate{TSource}(IEnumerable{TSource}, Func{TSource, TSource, TSource})"/> method, this method potentially asynchronously enumerates this <see cref="IAsyncEnumerable{T}"/> and aggregates a single value using the given <paramref name="asyncFunc"/> potentially asynchronous callback. /// </summary> /// <typeparam name="T">The type of elements being enumerated.</typeparam> /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param> /// <param name="asyncFunc">The potentially asynchronous callback function to perform aggregation. First argument is previous element, second argument is current element, and return value is the new aggregated value.</param> /// <returns>An aggregated value.</returns> /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">If <paramref name="asyncFunc"/> is <c>null</c>.</exception> /// <exception cref="InvalidOperationException">If this <see cref="IAsyncEnumerable{T}"/> does not contain at least one element.</exception> public async Task <T> AggregateAsync <T>(IAsyncEnumerable <T> source, Func <T, T, ValueTask <T> > asyncFunc) { ArgumentValidator.ValidateNotNullReference(source); ArgumentValidator.ValidateNotNull(nameof(asyncFunc), asyncFunc); var state = INITIAL; T prev = default; await source.EnumerateAsync(async item => { if (state == INITIAL) { prev = item; Interlocked.Exchange(ref state, FIRST_SEEN); } else { prev = await asyncFunc(prev, item); } }); return(state == FIRST_SEEN ? prev : throw AsyncProviderUtilities.EmptySequenceException()); }
public Task <T> AggregateAsync <T>(IAsyncEnumerable <T> source, Func <T, T, ValueTask <T> > asyncFunc) => throw AsyncProviderUtilities.EmptySequenceException();