File: System\Linq\Parallel\QueryOperators\Inlined\InlinedAggregationOperatorEnumerator.cs
Web Access
Project: src\src\libraries\System.Linq.Parallel\src\System.Linq.Parallel.csproj (System.Linq.Parallel)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// InlinedAggregationOperatorEnumerator.cs
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
using System.Diagnostics.CodeAnalysis;
using System.Threading;
 
namespace System.Linq.Parallel
{
    //---------------------------------------------------------------------------------------
    // Inlined aggregate operators for finding the min/max values for primitives (int, long, float,
    // double, decimal).  Versions are also offered for the nullable primitives (int?, long?, float?,
    // double?, decimal?), which differ slightly in behavior: they return a null value for empty
    // streams, whereas the ordinary primitive versions throw.
    //
 
    //---------------------------------------------------------------------------------------
    // Inlined average operators for primitives (int, long, float, double, decimal), and the
    // nullable variants.  The difference between the normal and nullable variety is that
    // nulls are skipped in tallying the count and sum for the average.
    //
 
    /// <summary>
    /// A class with some shared implementation between all aggregation enumerators.
    /// </summary>
    /// <typeparam name="TIntermediate"></typeparam>
    internal abstract class InlinedAggregationOperatorEnumerator<TIntermediate> : QueryOperatorEnumerator<TIntermediate, int>
    {
        private readonly int _partitionIndex; // This partition's unique index.
        private bool _done;
        protected CancellationToken _cancellationToken;
 
        //---------------------------------------------------------------------------------------
        // Instantiates a new aggregation operator.
        //
 
        internal InlinedAggregationOperatorEnumerator(int partitionIndex, CancellationToken cancellationToken)
        {
            _partitionIndex = partitionIndex;
            _cancellationToken = cancellationToken;
        }
 
        //---------------------------------------------------------------------------------------
        // Tallies up the sum of the underlying data source, walking the entire thing the first
        // time MoveNext is called on this object. There is a boilerplate variant used by callers,
        // and then one that is used for extensibility by subclasses.
        //
 
        internal sealed override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TIntermediate currentElement, ref int currentKey)
        {
            if (!_done && MoveNextCore(ref currentElement))
            {
                // A reduction's "index" is the same as its partition number.
                currentKey = _partitionIndex;
                _done = true;
                return true;
            }
 
            return false;
        }
 
        protected abstract bool MoveNextCore([MaybeNullWhen(false), AllowNull] ref TIntermediate currentElement);
    }
}