Ejemplo n.º 1
0
    /// <summary>
    /// This extension method creates a new <see cref="ConcurrentQueue{T}"/> and possibly concurrently enumerates this <see cref="IAsyncEnumerable{T}"/>, adding each encountered item to the <see cref="ConcurrentQueue{T}"/>.
    /// </summary>
    /// <typeparam name="T">The type of items being enumerated.</typeparam>
    /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
    /// <returns>A new <see cref="ConcurrentQueue{T}"/> holding all items encountered while enumerating this <see cref="IAsyncEnumerable{T}"/>.</returns>
    /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
    public static async Task <ConcurrentQueue <T> > ToConcurrentQueueAsync <T>(this IAsyncEnumerable <T> enumerable)
    {
        var retVal = new ConcurrentQueue <T>();
        await enumerable.AddToConcurrentCollectionAsync(retVal, (queue, item) => queue.Enqueue(item));

        return(retVal);
    }
Ejemplo n.º 2
0
    /// <summary>
    /// This extension method creates a new <see cref="ConcurrentStack{T}"/> and possibly concurrently enumerates this <see cref="IAsyncEnumerable{T}"/>, adding each encountered item to the <see cref="ConcurrentStack{T}"/>.
    /// </summary>
    /// <typeparam name="T">The type of items being enumerated.</typeparam>
    /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
    /// <returns>A new <see cref="ConcurrentStack{T}"/> holding all items encountered while enumerating this <see cref="IAsyncEnumerable{T}"/>.</returns>
    /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
    public static async Task <ConcurrentStack <T> > ToConcurrentStackAsync <T>(this IAsyncEnumerable <T> enumerable)
    {
        var retVal = new ConcurrentStack <T>();
        await enumerable.AddToConcurrentCollectionAsync(retVal, (stack, item) => stack.Push(item));

        return(retVal);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// This extension method creates a new <see cref="ConcurrentBag{T}"/> and possibly concurrently enumerates this <see cref="IAsyncEnumerable{T}"/>, adding each encountered item to the <see cref="ConcurrentBag{T}"/>.
    /// </summary>
    /// <typeparam name="T">The type of items being enumerated.</typeparam>
    /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
    /// <returns>A new <see cref="ConcurrentBag{T}"/> holding all items encountered while enumerating this <see cref="IAsyncEnumerable{T}"/>.</returns>
    /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
    public static async Task <ConcurrentBag <T> > ToConcurrentBagAsync <T>(this IAsyncEnumerable <T> enumerable)
    {
        var retVal = new ConcurrentBag <T>();
        await enumerable.AddToConcurrentCollectionAsync(retVal, (bag, item) => bag.Add(item));

        return(retVal);
    }
Ejemplo n.º 4
0
    /// <summary>
    /// This extension method creates a new <see cref="ConcurrentStack{T}"/> and possibly concurrently enumerates this <see cref="IAsyncEnumerable{T}"/>, adding each encountered item transformed by given <paramref name="selector"/> to the <see cref="ConcurrentStack{T}"/>.
    /// </summary>
    /// <typeparam name="T">The type of items being enumerated.</typeparam>
    /// <typeparam name="U">The type of items added to <see cref="ConcurrentStack{T}"/>.</typeparam>
    /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
    /// <param name="selector">The callback to asynchronously select an object to be added to <see cref="ConcurrentStack{T}"/>.</param>
    /// <returns>A new <see cref="ConcurrentStack{T}"/> holding all transformed items encountered while enumerating this <see cref="IAsyncEnumerable{T}"/>.</returns>
    /// <remarks>
    /// <para>
    /// The motivation for this method is that often the items enumerated by <see cref="IAsyncEnumerable{T}"/> are "incomplete" in a sense that they require additional asynchronous processing (e.g. reading SQL row values, or reading the content of HTTP response).
    /// Using <see cref="Select{T, U}(IAsyncEnumerable{T}, Func{T, ValueTask{U}})"/> method will force the <see cref="IAsyncEnumerable{T}"/> into sequential enumerable, which may be undesired.
    /// Therefore, using this method directly it is possible to enumerate this <see cref="IAsyncEnumerable{T}"/> possibly concurrently into <see cref="ConcurrentStack{T}"/> while transforming each enumerable item into other type.
    /// </para>
    /// </remarks>
    public static async Task <ConcurrentStack <U> > ToConcurrentStackAsync <T, U>(this IAsyncEnumerable <T> enumerable, Func <T, Task <U> > selector)
    {
        ArgumentValidator.ValidateNotNull(nameof(selector), selector);
        var retVal = new ConcurrentStack <U>();
        await enumerable.AddToConcurrentCollectionAsync(retVal, async ( stack, item ) => stack.Push(await selector(item)));

        return(retVal);
    }
Ejemplo n.º 5
0
    /// <summary>
    /// This extension method will possibly concurrently enumerate this <see cref="IAsyncEnumerable{T}"/> into a <see cref="ConcurrentDictionary{TKey, TValue}"/>.
    /// </summary>
    /// <typeparam name="T">The type of items being enumerated.</typeparam>
    /// <typeparam name="TKey">The type of dictionary keys.</typeparam>
    /// <typeparam name="TValue">The type of dictionary values.</typeparam>
    /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
    /// <param name="keySelector">The callback to potentially asynchronously create a dictionary key from enumerable item.</param>
    /// <param name="valueSelector">The callback to potentially asynchronously create a dictionary value from enumerable item.</param>
    /// <param name="equalityComparer">The optional <see cref="IEqualityComparer{T}"/> to use when creating dictionary.</param>
    /// <returns>Asynchronously returns a <see cref="IDictionary{TKey, TValue}"/> containing keys and values as returned by <paramref name="keySelector"/> and <paramref name="valueSelector"/>.</returns>
    /// <remarks>
    /// <para>
    /// TODO currently this will not throw if there are duplicate keys, unlike <see cref="ToDictionaryAsync{T, TKey, TValue}(IAsyncEnumerable{T}, Func{T, TKey}, Func{T, TValue}, IEqualityComparer{TKey})"/> method.
    /// The behaviour needs to be unified/parametrized at some point.
    /// </para>
    /// </remarks>
    /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
    /// <exception cref="ArgumentNullException">If either of <paramref name="keySelector"/> or <paramref name="valueSelector"/> is <c>null</c>.</exception>
    public static async Task <ConcurrentDictionary <TKey, TValue> > ToConcurrentDictionaryAsync <T, TKey, TValue>(
        this IAsyncEnumerable <T> enumerable,
        Func <T, ValueTask <TKey> > keySelector,
        Func <T, ValueTask <TValue> > valueSelector,
        IEqualityComparer <TKey> equalityComparer = null
        )
    {
        ArgumentValidator.ValidateNotNullReference(enumerable);
        ArgumentValidator.ValidateNotNull(nameof(keySelector), keySelector);
        ArgumentValidator.ValidateNotNull(nameof(valueSelector), valueSelector);

        // Normal Dictionary<TKey, TValue> constructor accepts null as equality comparer, but ConcurrentDictionary throws... sigh. :)
        var retVal = new ConcurrentDictionary <TKey, TValue>(equalityComparer ?? EqualityComparer <TKey> .Default);
        await enumerable.AddToConcurrentCollectionAsync(retVal, async ( dictionary, item ) => dictionary.TryAdd(await keySelector(item), await valueSelector(item)));

        return(retVal);
    }