ParallelEnumerable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / ParallelEnumerable.cs / 1305376 / ParallelEnumerable.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// ParallelEnumerable.cs 
//
// [....] 
//
// The standard IEnumerable-based LINQ-to-Objects query provider. This class basically
// mirrors the System.Linq.Enumerable class, but (1) takes as input a special "parallel
// enumerable" data type and (2) uses an alternative implementation of the operators. 
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 
 
using System;
using System.Collections.Generic; 
using System.Threading;
using System.Diagnostics.Contracts;
using System.Linq.Parallel;
using System.Collections.Concurrent; 
using System.Collections;
using System.Threading.Tasks; 
 
namespace System.Linq
{ 
    //------------------------------------------------------------------------------------
    // Languages like C# and VB that support query comprehensions translate queries
    // into calls to a query provider which creates executable representations of the
    // query. The LINQ-to-Objects provider is implemented as a static class with an 
    // extension method per-query operator; when invoked, these return enumerable
    // objects that implement the querying behavior. 
    // 
    // We have a new sequence class for two reasons:
    // 
    //     (1) Developers can opt in to parallel query execution piecemeal, by using
    //         a special AsParallel API to wrap the data source.
    //     (2) Parallel LINQ uses a new representation for queries when compared to LINQ,
    //         which we must return from the new sequence operator implementations. 
    //
    // Comments and documentation will be somewhat light in this file. Please refer 
    // to the "official" Standard Query Operators specification for details on each API: 
    // http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/Standard_Query_Operators.doc
    // 
    // Notes:
    //     The Standard Query Operators herein should be semantically equivalent to
    //     the specification linked to above. In some cases, we offer operators that
    //     aren't available in the sequential LINQ library; in each case, we will note 
    //     why this is needed.
    // 
 
    /// 
    /// Provides a set of methods for querying objects that implement 
    /// ParallelQuery{TSource}.  This is the parallel equivalent of
    /// .
    /// 
    public static class ParallelEnumerable 
    {
        // We pass this string constant to an attribute constructor. Unfortunately, we cannot access resources from 
        // an attribute constructor, so we have to store this string in source code. 
        private const string RIGHT_SOURCE_NOT_PARALLEL_STR =
            "The second data source of a binary operator must be of type System.Linq.ParallelQuery rather than " 
            + "System.Collections.Generic.IEnumerable. To fix this problem, use the AsParallel() extension method "
            + "to convert the right data source to System.Linq.ParallelQuery.";

        //----------------------------------------------------------------------------------- 
        // Converts any IEnumerable into something that can be the target of parallel
        // query execution. 
        // 
        // Arguments:
        //     source              - the enumerable data source 
        //     options             - query analysis options to override the defaults
        //     degreeOfParallelism - the DOP to use instead of the system default, if any
        //
        // Notes: 
        //     If the argument is already a parallel enumerable, such as a query operator,
        //     no new objects are allocated. Otherwise, a very simple wrapper is instantiated 
        //     that exposes the IEnumerable as a ParallelQuery. 
        //
 
        /// 
        /// Enables parallelization of a query.
        /// 
        /// The type of elements of . 
        /// An 
        /// to convert to a . 
        /// The source as a  to bind to 
        /// ParallelEnumerable extension methods.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery AsParallel(this IEnumerable source)
        { 
            if (source == null)
            { 
                throw new ArgumentNullException("source"); 
            }
 
            return new ParallelEnumerableWrapper(source);
        }

        ///  
        /// Enables parallelization of a query, as sourced by a partitioner
        /// responsible for splitting the input sequence into partitions. 
        ///  
        /// The type of elements of .
        /// A partitioner over the input sequence. 
        /// The  as a ParallelQuery to bind to ParallelEnumerable extension methods.
        /// 
        /// The source partitioner's GetOrderedPartitions method is used when ordering is enabled,
        /// whereas the partitioner's GetPartitions is used if ordering is not enabled (the default). 
        /// The source partitioner's GetDynamicPartitions and GetDynamicOrderedPartitions are not used.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery AsParallel(this Partitioner source)
        {
            if (source == null)
            { 
                throw new ArgumentNullException("source");
            } 
 
            return new PartitionerQueryOperator(source);
        } 


        /// 
        /// Enables treatment of a data source as if it was ordered, overriding the default of unordered. 
        /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
        /// and ParallelEnumerable.Repeat. 
        ///  
        /// The type of elements of .
        /// The input sequence. 
        /// 
        /// Thrown if  is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// A natural tension exists between performance and preserving order in parallel processing. By default,
        /// a parallelized query behaves as if the ordering of the results is arbitrary 
        /// unless AsOrdered is applied or there is an explicit OrderBy operator in the query.
        /// 
        /// The source sequence which will maintain ordering in the query.
        public static ParallelQuery AsOrdered(this ParallelQuery source) 
        {
            if (source == null) 
            { 
                throw new ArgumentNullException("source");
            } 

            if (!(source is ParallelEnumerableWrapper || source is IParallelPartitionable))
            {
                PartitionerQueryOperator partitionerOp = source as PartitionerQueryOperator; 
                if (partitionerOp != null)
                { 
                    if (!partitionerOp.Orderable) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_PartitionerNotOrderable)); 
                    }
                }
                else
                { 
                    throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidAsOrderedCall));
                } 
            } 

            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(source), true); 
        }

        /// 
        /// Enables treatment of a data source as if it was ordered, overriding the default of unordered. 
        /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
        /// and ParallelEnumerable.Repeat. 
        ///  
        /// The input sequence.
        ///  
        /// Thrown if the  is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
        /// 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// A natural tension exists between performance and preserving order in parallel processing. By default, 
        /// a parallelized query behaves as if the ordering of the results is arbitrary unless AsOrdered
        /// is applied or there is an explicit OrderBy operator in the query. 
        /// 
        /// The source sequence which will maintain ordering in the query.
        public static ParallelQuery AsOrdered(this ParallelQuery source)
        { 
            if (source == null)
            { 
                throw new ArgumentNullException("source"); 
            }
 
            ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
            if (wrapper == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidNonGenericAsOrderedCall)); 
            }
 
            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(wrapper), true); 
        }
 
        /// 
        /// Allows an intermediate query to be treated as if no ordering is implied among the elements.
        /// 
        ///  
        /// AsUnordered may provide
        /// performance benefits when ordering is not required in a portion of a query. 
        ///  
        /// The type of elements of .
        /// The input sequence. 
        /// The source sequence with arbitrary order.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery AsUnordered(this ParallelQuery source)
        { 
            if (source == null) 
            {
                throw new ArgumentNullException("source"); 
            }

            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(source), false);
        } 

        ///  
        /// Enables parallelization of a query. 
        /// 
        /// An  to convert 
        /// to a .
        /// 
        /// The source as a ParallelQuery to bind to
        /// ParallelEnumerable extension methods. 
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery AsParallel(this IEnumerable source) 
        {
            if (source == null) throw new ArgumentNullException("source");

            return new ParallelEnumerableWrapper(source); 
        }
 
 
        //-----------------------------------------------------------------------------------
        // Converts a parallel enumerable into something that forces sequential execution. 
        //
        // Arguments:
        //     source - the parallel enumerable data source
        // 

        ///  
        /// Converts a  into an 
        ///  to force sequential
        /// evaluation of the query. 
        /// 
        /// The type of elements of .
        /// A  to convert to an .
        /// The source as an  
        /// to bind to sequential extension methods.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static IEnumerable AsSequential(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");

            // Ditch the wrapper, if there is one. 
            ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
            if (wrapper != null) 
            { 
                return wrapper.WrappedEnumerable;
            } 
            else
            {
                return source;
            } 
        }
 
 
        /// 
        /// Sets the task scheduler to execute the query. 
        /// 
        /// The type of elements of .
        /// A ParallelQuery on which to set the task scheduler option.
        /// Task scheduler to execute the query. 
        /// ParallelQuery representing the same query as source, but with the task scheduler option set.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// WithTaskScheduler is used multiple times in the query.
        /// 
        internal static ParallelQuery WithTaskScheduler(this ParallelQuery source, TaskScheduler taskScheduler)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (taskScheduler == null) throw new ArgumentNullException("taskScheduler"); 
 
            QuerySettings settings = QuerySettings.Empty;
            settings.TaskScheduler = taskScheduler; 

            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        } 

        ///  
        /// Sets the degree of parallelism to use in a query. Degree of parallelism is the maximum number of concurrently 
        /// executing tasks that will be used to process the query.
        ///  
        /// The type of elements of .
        /// A ParallelQuery on which to set the limit on the degrees of parallelism.
        /// The degree of parallelism for the query.
        /// ParallelQuery representing the same query as source, with the limit on the degrees of parallelism set. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// WithDegreeOfParallelism is used multiple times in the query. 
        /// 
        /// 
        ///  is less than 1 or greater than 63.
        ///  
        public static ParallelQuery WithDegreeOfParallelism(this ParallelQuery source, int degreeOfParallelism)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (degreeOfParallelism < 1 || degreeOfParallelism > Scheduling.MAX_SUPPORTED_DOP)
            { 
                throw new ArgumentOutOfRangeException("degreeOfParallelism");
            }

            QuerySettings settings = QuerySettings.Empty; 
            settings.DegreeOfParallelism = degreeOfParallelism;
 
            return new QueryExecutionOption( 
                QueryOperator.AsQueryOperator(source), settings);
        } 

        /// 
        /// Sets the  to associate with the query.
        ///  
        /// The type of elements of .
        /// A ParallelQuery on which to set the option. 
        /// A cancellation token. 
        /// ParallelQuery representing the same query as source, but with the 
        /// registered. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// WithCancellation is used multiple times in the query.
        ///  
        ///  
        /// The  associated with the  has been disposed.
        ///  
        public static ParallelQuery WithCancellation(this ParallelQuery source, CancellationToken cancellationToken)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            // also a convenience check whether the cancellationTokenSource backing the token is already disposed.
            // do this via a dummy registration as there is no public IsDipsosed property on CT. 
            CancellationTokenRegistration dummyRegistration = new CancellationTokenRegistration(); 
            try
            { 
                dummyRegistration = cancellationToken.Register(() => { });
            }
            catch (ObjectDisposedException)
            { 
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithCancellation_TokenSourceDisposed), "cancellationToken");
            } 
            finally 
            {
                dummyRegistration.Dispose(); 
            }

            QuerySettings settings = QuerySettings.Empty;
            settings.CancellationState = new CancellationState(cancellationToken); 

            return new QueryExecutionOption( 
                QueryOperator.AsQueryOperator(source), settings); 
        }
 
        /// 
        /// Sets the execution mode of the query.
        /// 
        /// The type of elements of . 
        /// A ParallelQuery on which to set the option.
        /// The mode in which to execute the query. 
        /// ParallelQuery representing the same query as source, but with the 
        ///  registered.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  is not a valid  value. 
        /// 
        ///  
        /// WithExecutionMode is used multiple times in the query. 
        /// 
        public static ParallelQuery WithExecutionMode(this ParallelQuery source, ParallelExecutionMode executionMode) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (executionMode != ParallelExecutionMode.Default && executionMode != ParallelExecutionMode.ForceParallelism)
            { 
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithQueryExecutionMode_InvalidMode));
            } 
 
            QuerySettings settings = QuerySettings.Empty;
            settings.ExecutionMode = executionMode; 

            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        } 

        ///  
        /// Sets the merge options for this query, which specify how the query will buffer output. 
        /// 
        /// The type of elements of . 
        /// A ParallelQuery on which to set the option.
        /// The merge optiosn to set for this query.
        /// ParallelQuery representing the same query as source, but with the
        ///  registered. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  is not a valid  value. 
        /// 
        /// 
        /// WithMergeOptions is used multiple times in the query.
        ///  
        public static ParallelQuery WithMergeOptions(this ParallelQuery source, ParallelMergeOptions mergeOptions)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (mergeOptions != ParallelMergeOptions.Default
                && mergeOptions != ParallelMergeOptions.AutoBuffered 
                && mergeOptions != ParallelMergeOptions.NotBuffered
                && mergeOptions != ParallelMergeOptions.FullyBuffered)
            {
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithMergeOptions_InvalidOptions)); 
            }
 
            QuerySettings settings = QuerySettings.Empty; 
            settings.MergeOptions = mergeOptions;
 
            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        }
 
        //-----------------------------------------------------------------------------------
        // Range generates a sequence of numbers that can be used as input to a query. 
        // 

        ///  
        /// Generates a parallel sequence of integral numbers within a specified range.
        /// 
        /// The value of the first integer in the sequence.
        /// The number of sequential integers to generate. 
        /// An IEnumerable<Int32> in C# or IEnumerable(Of Int32) in
        /// Visual Basic that contains a range of sequential integral numbers. 
        ///  
        ///  is less than 0
        /// -or- 
        ///  +  - 1 is larger than .
        /// 
        public static ParallelQuery Range(int start, int count)
        { 
            if (count < 0 || (count > 0 && Int32.MaxValue - (count - 1) < start)) throw new ArgumentOutOfRangeException("count");
            return new RangeEnumerable(start, count); 
        } 

        //------------------------------------------------------------------------------------ 
        // Repeat just generates a sequence of size 'count' containing 'element'.
        //

        ///  
        /// Generates a parallel sequence that contains one repeated value.
        ///  
        /// The type of the value to be repeated in the result sequence. 
        /// The value to be repeated.
        /// The number of times to repeat the value in the generated sequence. 
        /// A sequence that contains a repeated value.
        /// 
        ///  is less than 0.
        ///  
        public static ParallelQuery Repeat(TResult element, int count)
        { 
            if (count < 0) throw new ArgumentOutOfRangeException("count"); 

            return new RepeatEnumerable(element, count); 
        }

        //-----------------------------------------------------------------------------------
        // Returns an always-empty sequence. 
        //
 
        ///  
        /// Returns an empty ParallelQuery{TResult} that has the specified type argument.
        ///  
        /// The type to assign to the type parameter of the returned
        /// generic sequence.
        /// An empty sequence whose type argument is .
        public static ParallelQuery Empty() 
        {
            return System.Linq.Parallel.EmptyEnumerable.Instance; 
        } 

        //------------------------------------------------------------------------------------ 
        // A new query operator that allows an arbitrary user-specified "action" to be
        // tacked on to the query tree. The action will be invoked for every element in the
        // underlying data source, avoiding a costly final merge in the query's execution,
        // which can lead to much better scalability. The caveat is that these occur in 
        // parallel, so the user providing an action must take care to eliminate shared state
        // accesses or to synchronize as appropriate. 
        // 
        // Arguments:
        //     source  - the data source over which the actions will be invoked 
        //     action  - a delegate representing the per-element action to be invoked
        //
        // Notes:
        //     Neither source nor action may be null, otherwise this method throws. 
        //
 
        ///  
        /// Invokes in parallel the specified action for each element in the .
        ///  
        /// 
        /// This is an efficient way to process the output from a parallelized query because it does
        /// not require a merge step at the end.  However, order of execution is non-deterministic.
        ///  
        /// The type of elements of .
        /// The  whose elements will be processed by 
        /// . 
        /// An Action to invoke on each element.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static void ForAll(this ParallelQuery source, Action action) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (action == null) throw new ArgumentNullException("action");
 
            // We just instantiate the forall operator and invoke it synchronously on this thread.
            // By the time it returns, the entire query has been executed and the actions run.. 
            new ForAllOperator(source, action).RunSynchronously(); 
        }
 


        /*====================================================================================
         * BASIC OPERATORS 
         *===================================================================================*/
 
        //----------------------------------------------------------------------------------- 
        // Where is an operator that filters any elements from the data source for which the
        // user-supplied predictate returns false. 
        //

        /// 
        /// Filters in parallel a sequence of values based on a predicate. 
        /// 
        /// The type of the elements of source. 
        /// A sequence to filter. 
        /// A function to test each element for a condition.
        /// A sequence that contains elements from the input sequence that satisfy 
        /// the condition.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Where(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new WhereQueryOperator(source, predicate);
        }

        ///  
        /// Filters in parallel a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.
        ///  
        /// The type of the elements of source. 
        /// A sequence to filter.
        /// A function to test each element for a condition. 
        /// A sequence that contains elements from the input sequence that satisfy the condition.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Where(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new IndexedWhereQueryOperator(source, predicate);
        }

        //------------------------------------------------------------------------------------ 
        // Select merely maps a selector delegate over each element in the data source.
        // 
 

        ///  
        /// Projects in parallel each element of a sequence into a new form.
        /// 
        /// The type of the elements of .
        /// The type of elements resturned by selector. 
        /// A sequence of values to invoke a transform function on.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the transform function on each 
        /// element of .
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Select(
            this ParallelQuery source, Func selector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector"); 

            return new SelectQueryOperator(source, selector); 
        }

        /// 
        /// Projects in parallel each element of a sequence into a new form by incorporating the element's index. 
        /// 
        /// The type of the elements of . 
        /// The type of elements resturned by selector. 
        /// A sequence of values to invoke a transform function on.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the transform function on each
        /// element of .
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Select( 
             this ParallelQuery source, Func selector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector");

            return new IndexedSelectQueryOperator(source, selector);
        } 

        //----------------------------------------------------------------------------------- 
        // Zip combines an outer and inner data source into a single output data stream. 
        //
 
        /// 
        /// Merges in parallel two sequences by using the specified predicate function.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the return elements. 
        /// The first sequence to zip. 
        /// The second sequence to zip.
        /// A function to create a result element from two matching elements. 
        /// 
        /// A sequence that has elements of type  that are obtained by performing
        /// resultSelector pairwise on two sequences. If the sequence lengths are unequal, this truncates
        /// to the length of the shorter sequence. 
        /// 
        ///  
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Zip( 
            this ParallelQuery first, ParallelQuery second, Func resultSelector)
        {
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            return new ZipQueryOperator(first, second, resultSelector); 
        }
 
        /// 
        /// This Zip overload should never be called.
        /// This method is marked as obsolete and always throws
        ///  when invoked. 
        /// 
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Zip with a left data source of type 
        ///  and a right data source of type . 
        /// Otherwise, the Zip operator would appear to be bind to the parallel implementation, but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Zip(
            this ParallelQuery first, IEnumerable second, Func resultSelector)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        } 
 
        //-----------------------------------------------------------------------------------
        // Join is an inner join operator, i.e. elements from outer with no inner matches 
        // will yield no results in the output data stream.
        //

        ///  
        /// Correlates in parallel the elements of two sequences based on matching keys.
        /// The default equality comparer is used to compare keys. 
        ///  
        /// The type of the elements of the first sequence.
        /// The type of the elements of the second sequence. 
        /// The type of the keys returned by the key selector functions.
        /// The type of the result elements.
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element of
        /// the first sequence. 
        /// A function to extract the join key from each element of 
        /// the second sequence.
        /// A function to create a result element from two matching elements. 
        /// A sequence that has elements of type  that are obtained by performing
        /// an inner join on two sequences.
        /// 
        ///  or  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Join( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector)
        {
            return Join(
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, null); 
        }
 
        ///  
        /// This Join overload should never be called.
        /// This method is marked as obsolete and always throws  when invoked. 
        /// 
        /// This type parameter is not used.
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage Join with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation. 
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Join(
            this ParallelQuery outer, IEnumerable inner,
            Func outerKeySelector, Func innerKeySelector,
            Func resultSelector) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        } 

        ///  
        /// Correlates in parallel the elements of two sequences based on matching keys.
        /// A specified IEqualityComparer{T} is used to compare keys.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements. 
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence.
        /// A function to extract the join key from each element
        /// of the second sequence. 
        /// A function to create a result element from two matching elements.
        /// An IEqualityComparer<(Of <(T>)>) to hash and compare keys. 
        /// A sequence that has elements of type  that are obtained by performing 
        /// an inner join on two sequences.
        ///  
        ///  or  or  or
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Join( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector, IEqualityComparer comparer) 
        {
            if (outer == null) throw new ArgumentNullException("outer"); 
            if (inner == null) throw new ArgumentNullException("inner");
            if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
            if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new JoinQueryOperator( 
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); 
        }
 
        /// 
        /// This Join overload should never be called.
        /// This method is marked as obsolete and always throws  when invoked.
        ///  
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Join with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Join(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }

        //----------------------------------------------------------------------------------- 
        // GroupJoin is an outer join operator, i.e. elements from outer with no inner matches
        // will yield results (empty lists) in the output data stream. 
        // 

        ///  
        /// Correlates in parallel the elements of two sequences based on equality of keys and groups the results.
        /// The default equality comparer is used to compare keys.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements. 
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence.
        /// A function to extract the join key from each element
        /// of the second sequence. 
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// A sequence that has elements of type  that are obtained by performing 
        /// a grouped join on two sequences.
        ///  
        ///  or  or  or
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupJoin( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func, TResult> resultSelector) 
        {
            return GroupJoin( 
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
        }

        ///  
        /// This GroupJoin overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        ///  
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This type parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of GroupJoin with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector,
            Func, TResult> resultSelector)
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }
 
        ///  
        /// Correlates in parallel the elements of two sequences based on key equality and groups the results.
        /// A specified IEqualityComparer{T} is used to compare keys. 
        /// 
        /// The type of the elements of the first sequence.
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements.
        /// The first sequence to join. 
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence. 
        /// A function to extract the join key from each element
        /// of the second sequence.
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// An IEqualityComparer<(Of <(T>)>) to hash and compare keys.
        /// A sequence that has elements of type  that are obtained by performing 
        /// a grouped join on two sequences. 
        /// 
        ///  or  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, ParallelQuery inner, 
            Func outerKeySelector, Func innerKeySelector,
            Func, TResult> resultSelector, IEqualityComparer comparer) 
        { 
            if (outer == null) throw new ArgumentNullException("outer");
            if (inner == null) throw new ArgumentNullException("inner"); 
            if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
            if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            return new GroupJoinQueryOperator(outer, inner,
                outerKeySelector, innerKeySelector, resultSelector, comparer); 
        } 

        ///  
        /// This GroupJoin overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        ///  
        /// This overload exists to disallow usage of GroupJoin with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector, 
            Func, TResult> resultSelector, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }

        //------------------------------------------------------------------------------------ 
        // SelectMany is a kind of nested loops join. For each element in the outer data
        // source, we enumerate each element in the inner data source, yielding the result 
        // with some kind of selection routine. A few different flavors are supported. 
        //
 
        /// 
        /// Projects in parallel each element of a sequence to an IEnumerable{T}
        /// and flattens the resulting sequences into one sequence.
        ///  
        /// The type of elements of .
        /// The type of the elements of the sequence returned by selector. 
        /// A sequence of values to project. 
        /// A transform function to apply to each element.
        /// A sequence whose elements are the result of invoking the one-to-many transform 
        /// function on each element of the input sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> selector) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (selector == null) throw new ArgumentNullException("selector"); 

            return new SelectManyQueryOperator(source, selector, null, null);
        }
 
        /// 
        /// Projects in parallel each element of a sequence to an IEnumerable{T}, and flattens the resulting 
        /// sequences into one sequence. The index of each source element is used in the projected form of 
        /// that element.
        ///  
        /// The type of elements of .
        /// The type of the elements of the sequence returned by selector.
        /// A sequence of values to project.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function on each element of the input sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SelectMany(
             this ParallelQuery source, Func> selector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector");
 
            return new SelectManyQueryOperator(source, null, selector, null); 
        }
 
        /// 
        /// Projects each element of a sequence to an IEnumerable{T},
        /// flattens the resulting sequences into one sequence, and invokes a result selector
        /// function on each element therein. 
        /// 
        /// The type of elements of . 
        /// The type of the intermediate elements collected by . 
        /// 
        /// A sequence of values to project. 
        /// A transform function to apply to each source element;
        /// the second parameter of the function represents the index of the source element.
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function  on each element of  and then mapping 
        /// each of those sequence elements and their corresponding source element to a result element. 
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> collectionSelector, 
            Func resultSelector)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new SelectManyQueryOperator(source, collectionSelector, null, resultSelector);
        }
 
        /// 
        /// Projects each element of a sequence to an IEnumerable{T}, flattens the resulting 
        /// sequences into one sequence, and invokes a result selector function on each element 
        /// therein. The index of each source element is used in the intermediate projected
        /// form of that element. 
        /// 
        /// The type of elements of .
        /// The type of the intermediate elements collected by
        /// . 
        /// The type of elements to return.
        /// A sequence of values to project. 
        /// A transform function to apply to each source element; 
        /// the second parameter of the function represents the index of the source element.
        /// A function to create a result element from an element from 
        /// the first sequence and a collection of matching elements from the second sequence.
        /// 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function  on each element of  and then mapping 
        /// each of those sequence elements and their corresponding source element to a
        /// result element. 
        ///  
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> collectionSelector, 
            Func resultSelector)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new SelectManyQueryOperator(source, null, collectionSelector, resultSelector);
        }
 
        //-----------------------------------------------------------------------------------
        // OrderBy and ThenBy establish an ordering among elements, using user-specified key 
        // selection and key comparison routines. There are also descending sort variants. 
        //
 
        /// 
        /// Sorts in parallel the elements of a sequence in ascending order according to a key.
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// To achieve a stable sort, change a query of the form: 
        /// var ordered = source.OrderBy((e) => e.k); 
        /// to instead be formed as:
        /// var ordered = source.Select((e,i) => new { E=e, I=i }).OrderBy((v) => v.i).Select((v) => v.e); 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource} whose elements are sorted 
        /// according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static OrderedParallelQuery OrderBy(
            this ParallelQuery source, Func keySelector)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 
 
            return new OrderedParallelQuery(
                new SortQueryOperator(source, keySelector, null, false)); 
        }

        /// 
        /// Sorts in parallel the elements of a sequence in ascending order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted according 
        /// to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderBy(
            this ParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery( 
                new SortQueryOperator(source, keySelector, comparer, false));
        }

        ///  
        /// Sorts in parallel the elements of a sequence in descending order according to a key.
        ///  
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for 
        /// an approach to implementing a stable sort.
        /// 
        /// The type of elements of .
        /// The type of the key returned by . 
        /// A sequence of values to order.
        /// A function to extract a key from an element. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted 
        /// descending according to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderByDescending(
            this ParallelQuery source, Func keySelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery(new SortQueryOperator(source, keySelector, null, true)); 
        }

        /// 
        /// Sorts the elements of a sequence in descending order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted descending 
        /// according to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderByDescending(
            this ParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery( 
                new SortQueryOperator(source, keySelector, comparer, true));
        }

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence
        /// in ascending order according to a key. 
        ///  
        /// 
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than 
        /// contains elements to sort. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource} whose elements are 
        /// sorted according to a key.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static OrderedParallelQuery ThenBy(
            this OrderedParallelQuery source, Func keySelector) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, null, false));
        } 

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence in 
        /// ascending order by using a specified comparer.
        ///  
        /// 
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by . 
        /// An OrderedParallelQuery{TSource} that contains
        /// elements to sort. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys.
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        public static OrderedParallelQuery ThenBy(
            this OrderedParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, comparer, false)); 
        } 

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence in
        /// descending order, according to a key.
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for 
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than contains
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static OrderedParallelQuery ThenByDescending(
            this OrderedParallelQuery source, Func keySelector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery( 
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, null, true));
        } 

        /// 
        /// Performs in parallel a subsequent ordering of the elements in a sequence in descending
        /// order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than contains 
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery ThenByDescending( 
            this OrderedParallelQuery source, Func keySelector, IComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, comparer, true));
        }
 
        //------------------------------------------------------------------------------------
        // A GroupBy operation groups inputs based on a key-selection routine, yielding a 
        // one-to-many value of key-to-elements to the consumer. 
        //
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource}than contains 
        /// elements to sort. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource}whose elements are sorted 
        /// descending according to a key.
        public static ParallelQuery> GroupBy(
            this ParallelQuery source, Func keySelector)
        { 
            return GroupBy(source, keySelector, null);
        } 
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by >.
        /// An OrderedParallelQuery{TSource} than contains 
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An IComparer{TSource} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new GroupByQueryOperator(source, keySelector, null, comparer);
        }

        ///  
        /// Groups in parallel the elements of a sequence according to a specified key selector function and
        /// projects the elements for each group by using a specified function. 
        ///  
        /// The type of elements of .
        /// The type of the key returned by . 
        /// The type of the elements in the IGrouping
        /// An OrderedParallelQuery<(Of <(TElement>)>) than contains
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// A function to map each source element to an element in an  IGrouping.
        /// A ParallelQuery<IGrouping<TKey, TElement>> in C# or 
        /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping 
        /// generic object contains a collection of objects of type  and a key.
        ///  
        ///  or  or
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector)
        { 
            return GroupBy(source, keySelector, elementSelector, null); 
        }
 
        /// 
        /// Groups in parallel the elements of a sequence according to a key selector function.
        /// The keys are compared by using a comparer and each group's elements are projected by
        /// using a specified function. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by . 
        /// The type of the elements in the IGrouping
        /// An OrderedParallelQuery{TSource}than contains elements to sort. 
        /// A function to extract a key from an element.
        /// A function to map each source element to an element in an  IGrouping.
        /// An IComparer{TSource} to compare keys.
        ///  
        /// A ParallelQuery{IGrouping{TKey, TElement}} in C# or
        /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping 
        /// generic object contains a collection of objects of type  and a key. 
        /// 
        ///  
        ///  or  or
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            return new GroupByQueryOperator(source, keySelector, elementSelector, comparer);
        }
 
        //
        // @PERF: We implement the GroupBy overloads that accept a resultSelector using a GroupBy followed by a Select. This 
        // adds some extra overhead, perhaps the most significant of which is an extra delegate invocation per element. 
        //
        // One possible solution is to create two different versions of the GroupByOperator class, where one has a TResult 
        // generic type and the other does not. Since this results in code duplication, we will avoid doing that for now.
        //
        // Another possible solution is to only have the more general GroupByOperator. Unfortunately, implementing the less
        // general overload (TResult == TElement) using the more general overload would likely result in unnecessary boxing 
        // and unboxing of each processed element in the cases where TResult is a value type, so that solution comes with
        // a significant cost, too. 
        // 

        ///  
        /// Groups in parallel the elements of a sequence according to a specified
        /// key selector function and creates a result value from each group and its key.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to create a result value from each group. 
        /// A collection of elements of type  where each element represents a
        /// projection over a group and its key.
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery GroupBy( 
            this ParallelQuery source, Func keySelector, Func, TResult> resultSelector)
 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");

            return source.GroupBy(keySelector) 
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); });
        } 
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function 
        /// and creates a result value from each group and its key. The keys are compared
        /// by using a specified comparer.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to create a result value from each group. 
        /// An IEqualityComparer{TKey} to compare keys.
        /// 
        /// An ParallelQuery<IGrouping<TKey, TResult>> in C# or
        /// ParallelQuery(Of IGrouping(Of TKey, TResult)) in Visual Basic where each 
        /// IGrouping<(Of <(TKey, TResult>)>) object contains a collection of objects
        /// of type  and a key. 
        ///  
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupBy(
            this ParallelQuery source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 
 
            return source.GroupBy(keySelector, comparer).Select, TResult>(
                delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); }); 
        }

        /// 
        /// Groups in parallel the elements of a sequence according to a specified key 
        /// selector function and creates a result value from each group and its key.
        /// The elements of each group are projected by using a specified function. 
        ///  
        /// The type of the elements of .
        /// The type of the key returned by . 
        /// The type of the elements in each
        /// IGrouping{TKey, TElement}.
        /// The type of the result value returned by .
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to map each source element to an element in an 
        /// IGrouping<TKey, TElement>. 
        /// A function to create a result value from each group.
        /// A collection of elements of type  where each element represents a 
        /// projection over a group and its key.
        /// 
        ///  or  or
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return source.GroupBy(keySelector, elementSelector)
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); });
        } 

        ///  
        /// Groups the elements of a sequence according to a specified key selector function and 
        /// creates a result value from each group and its key. Key values are compared by using a
        /// specified comparer, and the elements of each group are projected by using a specified function. 
        /// 
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the elements in each 
        /// IGrouping{TKey, TElement}.
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to map each source element to an element in an 
        /// IGrouping{Key, TElement}.
        /// A function to create a result value from each group.
        /// An IEqualityComparer{TKey} to compare keys.
        /// A collection of elements of type  where each element represents a 
        /// projection over a group and its key.
        ///  
        ///  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery GroupBy(
            this ParallelQuery source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer)
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return source.GroupBy(keySelector, elementSelector, comparer) 
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); }); 
        }
 
        /*====================================================================================
         * AGGREGATION OPERATORS
         *===================================================================================*/
 
        //-----------------------------------------------------------------------------------
        // Internal helper method that constructs an aggregation query operator and performs 
        // the actual execution/reduction before returning the result. 
        //
        // Arguments: 
        //     source  - the data source over which aggregation is performed
        //     reduce  - the binary reduction operator
        //     options - whether the operator is associative, commutative, both, or neither
        // 
        // Return Value:
        //     The result of aggregation. 
        // 

        private static T PerformAggregation(this ParallelQuery source, 
            Func reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
        {
            Contract.Assert(source != null);
            Contract.Assert(reduce != null); 
            Contract.Assert(Enum.IsDefined(typeof(QueryAggregationOptions), options), "enum is out of range");
 
            AssociativeAggregationOperator op = new AssociativeAggregationOperator( 
                source, seed, null, seedIsSpecified, reduce, reduce, delegate(T obj) { return obj; }, throwIfEmpty, options);
            return op.Aggregate(); 
        }


        ///  
        /// Run an aggregation sequentially. If the user-provided reduction function throws an exception, wrap
        /// it with an AggregateException. 
        ///  
        /// 
        ///  
        /// 
        /// if true, use the seed provided in the method argument
        /// if false, use the first element of the sequence as the seed instead
        ///  
        /// 
        private static TAccumulate PerformSequentialAggregation( 
            this ParallelQuery source, TAccumulate seed, bool seedIsSpecified, Func func) 
        {
            Contract.Assert(source != null); 
            Contract.Assert(func != null);
            Contract.Assert(seedIsSpecified || typeof(TSource) == typeof(TAccumulate));

            using(IEnumerator enumerator = source.GetEnumerator()) 
            {
                TAccumulate acc; 
                if (seedIsSpecified) 
                {
                    acc = seed; 
                }
                else
                {
                    // Take the first element as the seed 
                    if (!enumerator.MoveNext())
                    { 
                        throw new InvalidOperationException(SR.GetString(SR.NoElements)); 
                    }
 
                    acc = (TAccumulate)(object)enumerator.Current;
                }

                while (enumerator.MoveNext()) 
                {
                    TSource elem = enumerator.Current; 
 
                    // If the user delegate throws an exception, wrap it with an AggregateException
                    try 
                    {
                        acc = func(acc, elem);
                    }
                    catch (ThreadAbortException) 
                    {
                        // Do not wrap ThreadAbortExceptions 
                        throw; 
                    }
                    catch (Exception e) 
                    {
                        throw new AggregateException(e);
                    }
                } 

                return acc; 
            } 
        }
 
        //------------------------------------------------------------------------------------
        // General purpose aggregation operators, allowing pluggable binary prefix operations.
        //
 
        /// 
        /// Applies in parallel an accumulator function over a sequence. 
        ///  
        /// The type of the elements of .
        /// A sequence to aggregate over. 
        /// An accumulator function to be invoked on each element.
        /// The final accumulator value.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static TSource Aggregate( 
            this ParallelQuery source, Func func) 
        {
            return Aggregate(source, func, QueryAggregationOptions.AssociativeCommutative); 
        }

        internal static TSource Aggregate(
            this ParallelQuery source, Func func, QueryAggregationOptions options) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (func == null) throw new ArgumentNullException("func"); 
            if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");
 
            if ((options & QueryAggregationOptions.Associative) != QueryAggregationOptions.Associative)
            {
                // Non associative aggregations must be run sequentially.  We run the query in parallel
                // and then perform the reduction over the resulting list. 
                return source.PerformSequentialAggregation(default(TSource), false, func);
            } 
            else 
            {
                // If associative, we can run this aggregation in parallel. The logic of the aggregation 
                // operator depends on whether the operator is commutative, so we also pass that information
                // down to the query planning/execution engine.
                return source.PerformAggregation(func, default(TSource), false, true, options);
            } 
        }
 
        ///  
        /// Applies in parallel an accumulator function over a sequence.
        /// The specified seed value is used as the initial accumulator value. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// A sequence to aggregate over. 
        /// The initial accumulator value.
        /// An accumulator function to be invoked on each element. 
        /// The final accumulator value. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TAccumulate Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func) 
        {
            return Aggregate(source, seed, func, QueryAggregationOptions.AssociativeCommutative);
        }
 
        internal static TAccumulate Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func, QueryAggregationOptions options) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (func == null) throw new ArgumentNullException("func"); 
            if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");

            return source.PerformSequentialAggregation(seed, true, func);
        } 

        ///  
        /// Applies in parallel an accumulator function over a sequence. The specified 
        /// seed value is used as the initial accumulator value, and the specified
        /// function is used to select the result value. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// The type of the resulting value. 
        /// A sequence to aggregate over.
        /// The initial accumulator value. 
        /// An accumulator function to be invoked on each element. 
        /// A function to transform the final accumulator value
        /// into the result value. 
        /// The transformed final accumulator value.
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TResult Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func,
            Func resultSelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (func == null) throw new ArgumentNullException("func"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            TAccumulate acc = source.PerformSequentialAggregation(seed, true, func);
            try
            {
                return resultSelector(acc); 
            }
            catch (ThreadAbortException) 
            { 
                // Do not wrap ThreadAbortExceptions
                throw; 
            }
            catch (Exception e)
            {
                throw new AggregateException(e); 
            }
        } 
 
        /// 
        /// Applies in parallel an accumulator function over a sequence. This overload is not 
        /// available in the sequential implementation.
        /// 
        /// 
        /// This overload is specific to processing a parallelized query. A parallelized query may 
        /// partition the data source sequence into several sub-sequences (partitions).
        /// The  is invoked on each element within partitions. 
        /// Each partition then yields a single accumulated result. The  
        /// is then invoked on the results of each partition to yield a single element. This element is then
        /// transformed by the  function. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// The type of the resulting value. 
        /// A sequence to aggregate over.
        /// The initial accumulator value. 
        ///  
        /// An accumulator function to be invoked on each element in a partition.
        ///  
        /// 
        /// An accumulator function to be invoked on the yielded element from each partition.
        /// 
        ///  
        /// A function to transform the final accumulator value into the result value.
        ///  
        /// The transformed final accumulator value. 
        /// 
        ///  or  
        /// or  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TResult Aggregate( 
            this ParallelQuery source, TAccumulate seed, Func updateAccumulatorFunc,
            Func combineAccumulatorsFunc, Func resultSelector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
            if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new AssociativeAggregationOperator( 
                source, seed, null, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
                false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
        }
 
        /// 
        /// Applies in parallel an accumulator function over a sequence.  This overload is not 
        /// available in the sequential implementation. 
        /// 
        ///  
        /// This overload is specific to parallelized queries. A parallelized query may partition the data source sequence
        /// into several sub-sequences (partitions). The  is invoked
        /// on each element within partitions. Each partition then yields a single accumulated result.
        /// The  
        /// is then invoked on the results of each partition to yield a single element. This element is then
        /// transformed by the  function. 
        ///  
        /// The type of the elements of .
        /// The type of the accumulator value. 
        /// The type of the resulting value.
        /// A sequence to aggregate over.
        /// 
        /// A function that returns the initial accumulator value. 
        /// 
        ///  
        /// An accumulator function to be invoked on each element in a partition. 
        /// 
        ///  
        /// An accumulator function to be invoked on the yielded element from each partition.
        /// 
        /// 
        /// A function to transform the final accumulator value into the result value. 
        /// 
        /// The transformed final accumulator value. 
        ///  
        ///  or  or 
        /// or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TResult Aggregate(
            this ParallelQuery source, 
            Func seedFactory,
            Func updateAccumulatorFunc,
            Func combineAccumulatorsFunc,
            Func resultSelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (seedFactory == null) throw new ArgumentNullException("seedFactory"); 
            if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
            if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");

            return new AssociativeAggregationOperator(
                source, default(TAccumulate), seedFactory, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector, 
                false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
        } 
 

        //----------------------------------------------------------------------------------- 
        // Count and LongCount reductions.
        //

        ///  
        /// Returns the number of elements in a parallel sequence.
        ///  
        /// The type of the elements of . 
        /// A sequence that contains elements to be counted.
        /// The number of elements in the input sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// The number of elements in source is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static int Count(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
 
            // If the data source is a collection, we can just return the count right away. 
            ParallelEnumerableWrapper sourceAsWrapper = source as ParallelEnumerableWrapper;
            if (sourceAsWrapper != null) 
            {
                ICollection sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection;
                if (sourceAsCollection != null)
                { 
                    return sourceAsCollection.Count;
                } 
            } 

            // Otherwise, enumerate the whole thing and aggregate a count. 
            checked
            {
                return new CountAggregationOperator(source).Aggregate();
            } 
        }
 
        ///  
        /// Returns a number that represents how many elements in the specified
        /// parallel sequence satisfy a condition. 
        /// 
        /// The type of the elements of .
        /// A sequence that contains elements to be counted.
        /// A function to test each element for a condition. 
        /// 
        /// A number that represents how many elements in the sequence satisfy the condition 
        /// in the predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The number of elements in source is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int Count(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            // Construct a where operator to filter out unmatching elements, and then aggregate. 
            checked
            { 
                return new CountAggregationOperator(Where(source, predicate)).Aggregate();
            }
        }
 
        /// 
        /// Returns an Int64 that represents the total number of elements in a parallel sequence. 
        ///  
        /// The type of the elements of .
        /// A sequence that contains elements to be counted. 
        /// The number of elements in the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The number of elements in source is larger than . 
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long LongCount(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
 
            // If the data source is a collection, we can just return the count right away.
            ParallelEnumerableWrapper sourceAsWrapper = source as ParallelEnumerableWrapper; 
            if (sourceAsWrapper != null)
            {
                ICollection sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection;
                if (sourceAsCollection != null) 
                {
                    return sourceAsCollection.Count; 
                } 
            }
 
            // Otherwise, enumerate the whole thing and aggregate a count.
            return new LongCountAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Returns an Int64 that represents how many elements in a parallel sequence satisfy a condition. 
        ///  
        /// The type of the elements of .
        /// A sequence that contains elements to be counted. 
        /// A function to test each element for a condition.
        /// 
        /// A number that represents how many elements in the sequence satisfy the condition
        /// in the predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The number of elements in source is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static long LongCount(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");

            // Construct a where operator to filter out unmatching elements, and then aggregate. 
            return new LongCountAggregationOperator(Where(source, predicate)).Aggregate();
        } 
 
        //-----------------------------------------------------------------------------------
        // Sum aggregations. 
        //

        /// 
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// The sum is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static int Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntSumAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static int? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntSumAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new LongSumAggregationOperator(source).Aggregate();
        } 

        ///  
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than . 
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long? Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableLongSumAggregationOperator(source).Aggregate(); 
        }
 
        /// 
        /// Computes in parallel the sum of a sequence of values.
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static float Sum(this ParallelQuery source) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new FloatSumAggregationOperator(source).Aggregate(); 
        }

        /// 
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static float? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableFloatSumAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Computes in parallel the sum of a sequence of values. 
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleSumAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDoubleSumAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the sum of a sequence of values.
        /// 
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new DecimalSumAggregationOperator(source).Aggregate();
        }

        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDecimalSumAggregationOperator(source).Aggregate();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static int Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        }

        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static int? Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum(); 
        }
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static long Sum(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Sum(); 
        }
 
        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static long? Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        }

        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Sum(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Sum(); 
        }

        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static double Sum(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Sum(); 
        }
 
        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static double? Sum(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Sum();
        } 

        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// The sum is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static decimal? Sum(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Sum();
        }
 
        //-----------------------------------------------------------------------------------
        // Helper methods used for Min/Max aggregations below. This class can create a whole 
        // bunch of type-specific delegates that are passed to the general aggregation 
        // infrastructure. All comparisons are performed using the Comparer.Default
        // comparator. LINQ doesn't offer a way to override this, so neither do we. 
        //
        // @PERF: we'll eventually want inlined primitive providers that use IL instructions
        //    for comparison instead of the Comparer.CompareTo method.
        // 

        //------------------------------------------------------------------------------------ 
        // Min aggregations. 
        //
 
        /// 
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static int Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Min(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntMinMaxAggregationOperator(source, -1).Aggregate();
        } 
 
        /// 
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static long Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new LongMinMaxAggregationOperator(source, -1).Aggregate();
        }

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long? Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableLongMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new FloatMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        /// 
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatMinMaxAggregationOperator(source, -1).Aggregate();
        }

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleMinMaxAggregationOperator(source, -1).Aggregate(); 
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDoubleMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        /// 
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal Min(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalMinMaxAggregationOperator(source, -1).Aggregate(); 
        }
 
        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal? Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalMinMaxAggregationOperator(source, -1).Aggregate(); 
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements and  is a non-nullable value type.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TSource Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return AggregationMinMaxHelpers.ReduceMin(source);
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static int Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        }

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value. 
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static int? Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        } 
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static long Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min();
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static long? Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min(); 
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        } 
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min(); 
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static double? Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min();
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value. 
        /// 
        /// The type of elements of .
        /// The type of the value returned by .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements and  is a non-nullable value type.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static TResult Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min();
        } 

        //----------------------------------------------------------------------------------- 
        // Max aggregations. 
        //
 
        /// 
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static int Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Max(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntMinMaxAggregationOperator(source, 1).Aggregate();
        } 
 
        /// 
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static long Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new LongMinMaxAggregationOperator(source, 1).Aggregate();
        }

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long? Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableLongMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new FloatMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        /// 
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatMinMaxAggregationOperator(source, 1).Aggregate();
        }

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleMinMaxAggregationOperator(source, 1).Aggregate(); 
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDoubleMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        /// 
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal Max(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalMinMaxAggregationOperator(source, 1).Aggregate(); 
        }
 
        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal? Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalMinMaxAggregationOperator(source, 1).Aggregate(); 
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements and  is a non-nullable value type. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TSource Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return AggregationMinMaxHelpers.ReduceMax(source);
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static int Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max();
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long? Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value.
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static float Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static float? Max(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Max();
        } 

        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        ///  contains no elements.
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static double Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value.
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double? Max(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Max();
        }

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static decimal Max(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Max();
        } 

        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal? Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max();
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value.
        ///  
        /// The type of elements of .
        /// The type of the value returned by .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements and  is a non-nullable value type.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TResult Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max();
        }
 
        //------------------------------------------------------------------------------------
        // Average aggregations. 
        // 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// The sum or count of the elements in the sequence is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntAverageAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new LongAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableLongAverageAggregationOperator(source).Aggregate();
        }

        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average. 
        /// The average of the sequence of values.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new FloatAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatAverageAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values.
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDoubleAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static decimal Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalAverageAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values. 
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal? Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static double Average(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Average(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double? Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        }

        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        }

        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average(); 
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        } 
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average(); 
        }

        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average(); 
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static double? Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average();
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average(); 
        }

        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Average(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Average(); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Any returns true if there exists an element for which the predicate returns true.
        // 

        /// 
        /// Determines in parallel whether any element of a sequence satisfies a condition.
        ///  
        /// The type of elements of .
        /// An IEnumerable whose elements to apply the predicate to. 
        /// A function to test each element for a condition. 
        /// 
        /// true if any elements in the source sequence pass the test in the specified predicate; otherwise, false. 
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static bool Any(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new AnyAllSearchOperator(source, true, predicate).Aggregate(); 
        }
 
        /// 
        /// Determines whether a parallel sequence contains any elements.
        /// 
        /// The type of elements of . 
        /// The IEnumerable to check for emptiness.
        /// true if the source sequence contains any elements; otherwise, false. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static bool Any(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 

            IEnumerator e;

            // @PERF: if we know the count, we can just return true if it's non-zero. 

            // If the source is a query operator, shut off pipelining. 
            QueryOperator asOperator = source as QueryOperator; 
            if (asOperator != null)
            { 
                e = asOperator.GetEnumerator(ParallelMergeOptions.FullyBuffered);
            }
            else
            { 
                e = source.GetEnumerator();
            } 
 
            // If the results are non-empty, return true. Otherwise, false.
            using (e) 
            {
                if (e.MoveNext())
                {
                    return true; 
                }
            } 
 
            return false;
        } 

        //-----------------------------------------------------------------------------------
        // All returns false if there exists an element for which the predicate returns false.
        // 

        ///  
        /// Determines in parallel whether all elements of a sequence satisfy a condition. 
        /// 
        /// The type of elements of . 
        /// A sequence whose elements to apply the predicate to.
        /// A function to test each element for a condition.
        /// 
        /// true if all elements in the source sequence pass the test in the specified predicate; otherwise, false. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static bool All(this ParallelQuery source, Func predicate) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new AnyAllSearchOperator(source, false, predicate).Aggregate();
        }
 
        //------------------------------------------------------------------------------------
        // Contains returns true if the specified value was found in the data source. 
        // 

        ///  
        /// Determines in parallel whether a sequence contains a specified element
        /// by using the default equality comparer.
        /// 
        /// The type of elements of . 
        /// A sequence in which to locate a value.
        /// The value to locate in the sequence. 
        ///  
        /// true if the source sequence contains an element that has the specified value; otherwise, false.
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static bool Contains(this ParallelQuery source, TSource value)
        {
            return Contains(source, value, null);
        } 

        ///  
        /// Determines in parallel whether a sequence contains a specified element by using a 
        /// specified IEqualityComparer{T}.
        ///  
        /// The type of elements of .
        /// A sequence in which to locate a value.
        /// The value to locate in the sequence.
        /// An equality comparer to compare values. 
        /// 
        /// true if the source sequence contains an element that has the specified value; otherwise, false. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static bool Contains(this ParallelQuery source, TSource value, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source");

            // @PERF: there are many simple optimizations we can make for collection types with known sizes.
 
            return new ContainsSearchOperator(source, value, comparer).Aggregate();
        } 
 
        /*===================================================================================
         * TOP (TAKE, SKIP) OPERATORS 
         *===================================================================================*/

        //-----------------------------------------------------------------------------------
        // Take will take the first [0..count) contiguous elements from the input. 
        //
 
        ///  
        /// Returns a specified number of contiguous elements from the start of a parallel sequence.
        ///  
        /// The type of elements of .
        /// The sequence to return elements from.
        /// The number of elements to return.
        ///  
        /// A sequence that contains the specified number of elements from the start of the input sequence.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Take(this ParallelQuery source, int count)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            if (count > 0)
            { 
                return new TakeOrSkipQueryOperator(source, count, true); 
            }
            else 
            {
                return ParallelEnumerable.Empty();
            }
        } 

        //----------------------------------------------------------------------------------- 
        // TakeWhile will take the first [0..N) contiguous elements, where N is the smallest 
        // index of an element for which the predicate yields false.
        // 

        /// 
        /// Returns elements from a parallel sequence as long as a specified condition is true.
        ///  
        /// The type of elements of .
        /// The sequence to return elements from. 
        /// A function to test each element for a condition. 
        /// 
        /// A sequence that contains the elements from the input sequence that occur before 
        /// the element at which the test no longer passes.
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery TakeWhile(this ParallelQuery source, Func predicate) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new TakeOrSkipWhileQueryOperator(source, predicate, null, true);
        }
 
        /// 
        /// Returns elements from a parallel sequence as long as a specified condition is true. 
        /// The element's index is used in the logic of the predicate function. 
        /// 
        /// The type of elements of . 
        /// The sequence to return elements from.
        /// 
        /// A function to test each source element for a condition; the second parameter of the
        /// function represents the index of the source element. 
        /// 
        ///  
        /// A sequence that contains elements from the input sequence that occur before 
        /// the element at which the test no longer passes.
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery TakeWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new TakeOrSkipWhileQueryOperator(source, null, predicate, true); 
        }

        //------------------------------------------------------------------------------------
        // Skip will take the last [count..M) contiguous elements from the input, where M is 
        // the size of the input.
        // 
 
        /// 
        /// Bypasses a specified number of elements in a parallel sequence and then returns the remaining elements. 
        /// 
        /// The type of elements of .
        /// The sequence to return elements from.
        /// The number of elements to skip before returning the remaining elements. 
        /// 
        /// A sequence that contains the elements that occur after the specified index in the input sequence. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Skip(this ParallelQuery source, int count)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // If the count is 0 (or less) we just return the whole stream. 
            if (count <= 0) 
            {
                return source; 
            }

            return new TakeOrSkipQueryOperator(source, count, false);
        } 

        //----------------------------------------------------------------------------------- 
        // SkipWhile will take the last [N..M) contiguous elements, where N is the smallest 
        // index of an element for which the predicate yields false, and M is the size of
        // the input data source. 
        //

        /// 
        /// Bypasses elements in a parallel sequence as long as a specified 
        /// condition is true and then returns the remaining elements.
        ///  
        /// The type of elements of . 
        /// The sequence to return elements from.
        /// A function to test each element for a condition. 
        /// A sequence that contains the elements from the input sequence starting at
        /// the first element in the linear series that does not pass the test specified by
        /// predicate.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SkipWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return new TakeOrSkipWhileQueryOperator(source, predicate, null, false);
        } 

        ///  
        /// Bypasses elements in a parallel sequence as long as a specified condition is true and 
        /// then returns the remaining elements. The element's index is used in the logic of
        /// the predicate function. 
        /// 
        /// The type of elements of .
        /// The sequence to return elements from.
        ///  
        /// A function to test each source element for a condition; the
        /// second parameter of the function represents the index of the source element. 
        ///  
        /// 
        /// A sequence that contains the elements from the input sequence starting at the 
        /// first element in the linear series that does not pass the test specified by
        /// predicate.
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SkipWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return new TakeOrSkipWhileQueryOperator(source, null, predicate, false);
        } 

        /*==================================================================================== 
         * SET OPERATORS 
         *===================================================================================*/
 
        //------------------------------------------------------------------------------------
        // Appends the second data source to the first, preserving order in the process.
        //
 
        /// 
        /// Concatenates two parallel sequences. 
        ///  
        /// The type of the elements of the input sequences.
        /// The first sequence to concatenate. 
        /// The sequence to concatenate to the first sequence.
        /// A sequence that contains the concatenated elements of the two input sequences.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Concat(this ParallelQuery first, ParallelQuery second) 
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 
            return new ConcatQueryOperator(first, second);
        }

        ///  
        /// This Concat overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage of Concat with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Concat operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Concat(this ParallelQuery first, IEnumerable second)
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }
 
        //----------------------------------------------------------------------------------- 
        // Compares two input streams pairwise for equality.
        // 

        /// 
        /// Determines whether two parallel sequences are equal by comparing the elements by using
        /// the default equality comparer for their type. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence to compare to second. 
        /// A sequence to compare to the first input sequence.
        ///  
        /// true if the two source sequences are of equal length and their corresponding elements
        /// are equal according to the default equality comparer for their type; otherwise, false.
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static bool SequenceEqual(this ParallelQuery first, ParallelQuery second) 
        {
            if (first == null) throw new ArgumentNullException("first"); 
            if (second == null) throw new ArgumentNullException("second"); 
            return SequenceEqual(first, second, null);
        } 

        /// 
        /// This SequenceEqual overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        /// 
        /// This type parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// Thrown every time this method is called.
        /// 
        /// This overload exists to disallow usage of SequenceEqual with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation. 
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static bool SequenceEqual(this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Determines whether two parallel sequences are equal by comparing their elements by 
        /// using a specified IEqualityComparer{T}. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence to compare to .
        /// A sequence to compare to the first input sequence.
        /// An IEqualityComparer<(Of <(T>)>) to use to compare elements.
        ///  
        /// true if the two source sequences are of equal length and their corresponding
        /// elements are equal according to the default equality comparer for their type; otherwise, false. 
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static bool SequenceEqual(this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second");

            // If comparer is null, use the default one 
            comparer = comparer ?? EqualityComparer.Default;
 
            QueryOperator leftOp = QueryOperator.AsQueryOperator(first); 
            QueryOperator rightOp = QueryOperator.AsQueryOperator(second);
 
            // We use a fully-qualified type name for Shared here to prevent the conflict between System.Linq.Parallel.Shared<>
            // and System.Threading.Shared<> in the 3.5 legacy build.
            QuerySettings settings = leftOp.SpecifiedQuerySettings.Merge(rightOp.SpecifiedQuerySettings)
                .WithDefaults() 
                .WithPerExecutionSettings(new CancellationTokenSource(), new System.Linq.Parallel.Shared(false));
 
            // If first.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException. 
            IEnumerator e1 = first.GetEnumerator();
            try 
            {
                // If second.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException.
                IEnumerator e2 = second.GetEnumerator();
                try 
                {
                    while (e1.MoveNext()) 
                    { 
                        if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
                    } 
                    if (e2.MoveNext()) return false;
                }
                catch (ThreadAbortException)
                { 
                    // Do not wrap ThreadAbortExceptions
                    throw; 
                } 
                catch (Exception ex)
                { 
                    ExceptionAggregator.ThrowOCEorAggregateException(ex, settings.CancellationState);
                }
                finally
                { 
                    DisposeEnumerator(e2, settings.CancellationState);
                } 
            } 
            finally
            { 
                DisposeEnumerator(e1, settings.CancellationState);
            }

            return true; 
        }
 
        ///  
        /// A helper method for SequenceEqual to dispose an enumerator. If an exception is thrown by the disposal,
        /// it gets wrapped into an AggregateException, unless it is an OCE with the query's CancellationToken. 
        /// 
        private static void DisposeEnumerator(IEnumerator e, CancellationState cancelState)
        {
            try 
            {
                e.Dispose(); 
            } 
            catch (ThreadAbortException)
            { 
                // Do not wrap ThreadAbortExceptions
                throw;
            }
            catch (Exception ex) 
            {
                ExceptionAggregator.ThrowOCEorAggregateException(ex, cancelState); 
            } 
        }
 
        /// 
        /// This SequenceEqual overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// Thrown every time this method is called.
        /// 
        /// This overload exists to disallow usage of SequenceEqual with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to sequential implementation. 
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static bool SequenceEqual(this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        //------------------------------------------------------------------------------------
        // Calculates the distinct set of elements in the single input data source. 
        // 

        ///  
        /// Returns distinct elements from a parallel sequence by using the
        /// default equality comparer to compare values.
        /// 
        /// The type of the elements of . 
        /// The sequence to remove duplicate elements from.
        /// A sequence that contains distinct elements from the source sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Distinct(
            this ParallelQuery source)
        {
            return Distinct(source, null); 
        }
 
        ///  
        /// Returns distinct elements from a parallel sequence by using a specified
        /// IEqualityComparer{T} to compare values. 
        /// 
        /// The type of the elements of .
        /// The sequence to remove duplicate elements from.
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains distinct elements from the source sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Distinct( 
            this ParallelQuery source, IEqualityComparer comparer)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            return new DistinctQueryOperator(source, comparer);
        } 
 
        //-----------------------------------------------------------------------------------
        // Calculates the union between the first and second data sources. 
        //

        /// 
        /// Produces the set union of two parallel sequences by using the default equality comparer. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence whose distinct elements form the first set for the union. 
        /// A sequence whose distinct elements form the second set for the union.
        /// A sequence that contains the elements from both input sequences, excluding duplicates. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Union( 
            this ParallelQuery first, ParallelQuery second)
        { 
            return Union(first, second, null); 
        }
 
        /// 
        /// This Union overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Union with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Union operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Union(
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Produces the set union of two parallel sequences by using a specified IEqualityComparer{T}. 
        ///  
        /// The type of the elements of the input sequences.
        /// A sequence whose distinct elements form the first set for the union. 
        /// A sequence whose distinct elements form the second set for the union.
        /// An IEqualityComparer<(Of <(T>)>) to compare values.
        /// A sequence that contains the elements from both input sequences, excluding duplicates.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Union( 
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second");

            return new UnionQueryOperator(first, second, comparer); 
        }
 
        ///  
        /// This Union overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        /// 
        /// This type parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Union with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Union operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Union( 
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }

        //-----------------------------------------------------------------------------------
        // Calculates the intersection between the first and second data sources. 
        //
 
        ///  
        /// Produces the set intersection of two parallel sequences by using the
        /// default equality comparer to compare values. 
        /// 
        /// The type of the elements of the input sequences.
        /// A sequence whose distinct elements that also appear in  will be returned. 
        /// 
        ///  
        /// A sequence whose distinct elements that also appear in the first sequence will be returned. 
        /// 
        /// A sequence that contains the elements that form the set intersection of two sequences. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Intersect( 
            this ParallelQuery first, ParallelQuery second)
        { 
            return Intersect(first, second, null); 
        }
 
        /// 
        /// This Intersect overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Intersect with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Intersect(
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Produces the set intersection of two parallel sequences by using 
        /// the specified IEqualityComparer{T} to compare values. 
        /// 
        /// The type of the elements of the input sequences. 
        /// 
        /// A sequence whose distinct elements that also appear in  will be returned.
        /// 
        ///  
        /// A sequence whose distinct elements that also appear in the first sequence will be returned.
        ///  
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains the elements that form the set intersection of two sequences.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Intersect(
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer) 
        {
            if (first == null) throw new ArgumentNullException("first"); 
            if (second == null) throw new ArgumentNullException("second"); 

            return new IntersectQueryOperator(first, second, comparer); 
        }

        /// 
        /// This Intersect overload should never be called. 
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage of Intersect with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Intersect(
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        } 
 
        //-----------------------------------------------------------------------------------
        // Calculates the relative complement of the first and second data sources, that is, 
        // the elements in first that are not found in second.
        //

        ///  
        /// Produces the set difference of two parallel sequences by using
        /// the default equality comparer to compare values. 
        ///  
        /// The type of the elements of the input sequences.
        ///  
        /// A sequence whose elements that are not also in  will be returned.
        /// 
        /// 
        /// A sequence whose elements that also occur in the first sequence will cause those 
        /// elements to be removed from the returned sequence.
        ///  
        /// A sequence that contains the set difference of the elements of two sequences. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Except(
            this ParallelQuery first, ParallelQuery second)
        { 
            return Except(first, second, null);
        } 
 
        /// 
        /// This Except overload should never be called. 
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Except with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Except operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Except( 
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }

        /// 
        /// Produces the set difference of two parallel sequences by using the 
        /// specified IEqualityComparer{T} to compare values.
        ///  
        /// The type of the elements of the input sequences. 
        /// A sequence whose elements that are not also in  will be returned.
        ///  
        /// A sequence whose elements that also occur in the first sequence will cause those elements
        /// to be removed from the returned sequence.
        /// 
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains the set difference of the elements of two sequences.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Except( 
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        {
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 

            return new ExceptQueryOperator(first, second, comparer); 
        } 

        ///  
        /// This Except overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Except with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Except operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Except(
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /*====================================================================================
         * DATA TYPE CONVERSION OPERATORS 
         *===================================================================================*/ 

        //----------------------------------------------------------------------------------- 
        // For compatability with LINQ. Changes the static type to be less specific if needed.
        //

        ///  
        /// Converts a  into an
        ///  to force sequential 
        /// evaluation of the query. 
        /// 
        /// The type of the elements of . 
        /// The sequence to type as .
        /// The input sequence types as .
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static IEnumerable AsEnumerable(this ParallelQuery source) 
        { 
            return AsSequential(source);
        } 

       //------------------------------------------------------------------------------------
        // Simply generates a single-dimensional array containing the elements from the
        // provided enumerable object. 
        //
 
        ///  
        /// Creates an array from a ParallelQuery{T}.
        ///  
        /// The type of the elements of .
        /// A sequence to create an array from.
        /// An array that contains the elements from the input sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static TSource[] ToArray(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
 
            QueryOperator asOperator = source as QueryOperator;
 
            if (asOperator != null)
            {
                return asOperator.ExecuteAndGetResultsAsArray();
            } 

            return ToList(source).ToArray(); 
        } 

        //------------------------------------------------------------------------------------ 
        // The ToList method is similar to the ToArray methods above, except that they return
        // List objects. An overload is provided to specify the length, if desired.
        //
 
        /// 
        /// Creates a List{T} from an ParallelQuery{T}. 
        ///  
        /// The type of the elements of .
        /// A sequence to create a List<(Of <(T>)>) from. 
        /// A List<(Of <(T>)>) that contains elements from the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static List ToList(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // Allocate a growable list (optionally passing the length as the initial size). 
            List list = new List(); 
            IEnumerator input;
            QueryOperator asOperator = source as QueryOperator; 

            if (asOperator != null)
            {
                if (asOperator.OrdinalIndexState == OrdinalIndexState.Indexible && asOperator.OutputOrdered) 
                {
                    // If the query is indexible and the output is ordered, we will use the array-based merge. 
                    // That way, we avoid the ordering overhead. Due to limitations of the List<> class, the 
                    // most efficient solution seems to be to first dump all results into the array, and then
                    // copy them over into a List<>. 
                    //
                    // The issue is that we cannot efficiently construct a List<> with a fixed size. We can
                    // construct a List<> with a fixed *capacity*, but we still need to call Add() N times
                    // in order to be able to index into the List<>. 
                    return new List(ToArray(source));
                } 
 
                // We will enumerate the list w/out pipelining.
 
                // @PERF: there are likely some cases, e.g. for very large data sets,
                //     where we want to use pipelining for this operation. It can reduce memory
                //     usage since, as we enumerate w/ pipelining off, we're already accumulating
                //     results into a buffer. As a matter of fact, there's probably a way we can 
                //     just directly use that buffer below instead of creating a new list.
 
                input = asOperator.GetEnumerator(ParallelMergeOptions.FullyBuffered); 
            }
            else 
            {
                input = source.GetEnumerator();
            }
 
            // Now, accumulate the results into a dynamically sized list, stopping if we reach
            // the (optionally specified) maximum length. 
            Contract.Assert(input != null); 
            using (input)
            { 
                while (input.MoveNext())
                {
                    list.Add(input.Current);
                } 
            }
 
            return list; 
        }
 
        //-----------------------------------------------------------------------------------
        // ToDictionary constructs a dictionary from an instance of ParallelQuery.
        // Each element in the enumerable is converted to a (key,value) pair using a pair
        // of lambda expressions specified by the caller. Different elements must produce 
        // different keys or else ArgumentException is thrown.
        // 
 
        /// 
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to 
        /// a specified key selector function.
        /// 
        /// The type of the elements of .
        /// The type of the key returned by . 
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from.
        /// A function to extract a key from each element. 
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains keys and values. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements.
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector) 
        {
            return ToDictionary(source, keySelector, EqualityComparer.Default); 
        } 

        ///  
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to a
        /// specified key selector function and key comparer.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from. 
        /// A function to extract a key from each element. 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains keys and values. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements. 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
            Dictionary result = new Dictionary(comparer);
 
            QueryOperator op = source as QueryOperator;
            IEnumerator input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true); 
 
            using(input)
            { 
                while (input.MoveNext())
                {
                    TKey key;
                    TSource val = input.Current; 
                    try
                    { 
                        key = keySelector(val); 
                    	result.Add(key, val);
                    } 
                    catch (ThreadAbortException)
                    {
                        // Do not wrap ThreadAbortExceptions
                        throw; 
                    }
                    catch (Exception ex) 
                    { 
                        throw new AggregateException(ex);
                    } 
                }
            }

            return result; 
        }
 
        ///  
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to specified
        /// key selector and element selector functions. 
        /// 
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the value returned by . 
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from.
        /// A function to extract a key from each element. 
        ///  
        /// A transform function to produce a result element value from each element.
        ///  
        /// 
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains values of type 
        /// selected from the input sequence
        ///  
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  produces a key that is a null reference (Nothing in Visual Basic). 
        /// -or-
        ///  produces duplicate keys for two elements.
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static Dictionary ToDictionary( 
            this ParallelQuery source, Func keySelector, Func elementSelector)
        {
            return ToDictionary(source, keySelector, elementSelector, EqualityComparer.Default);
        } 

        ///  
        /// Creates a Dictionary{TKey,TValue from a ParallelQuery{T} according to a 
        /// specified key selector function, a comparer, and an element selector function.
        ///  
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the value returned by .
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from. 
        /// A function to extract a key from each element.
        /// A transform function to produce a result element 
        /// value from each element. 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        ///  
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains values of type 
        /// selected from the input sequence
        /// 
        ///  
        ///  or  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements.
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            // comparer may be null. In that case, the Dictionary constructor will use the default comparer. 
            Dictionary result = new Dictionary(comparer); 

            QueryOperator op = source as QueryOperator; 
            IEnumerator input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);

            using(input)
            { 
                while (input.MoveNext())
                { 
                    TSource src = input.Current; 

                    try 
                    {
                        result.Add(keySelector(src), elementSelector(src));
                    }
                    catch (ThreadAbortException) 
                    {
                        // Do not wrap ThreadAbortExceptions 
                        throw; 
                    }
                    catch(Exception ex) 
                    {
                        throw new AggregateException(ex);
                    }
                } 
            }
 
            return result; 
        }
 
        //------------------------------------------------------------------------------------
        // ToLookup constructs a lookup from an instance of ParallelQuery.
        // Each element in the enumerable is converted to a (key,value) pair using a pair
        // of lambda expressions specified by the caller. Multiple elements are allowed 
        // to produce the same key.
        // 
 
        /// 
        /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified key selector function. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from. 
        /// A function to extract a key from each element.
        /// A Lookup<(Of <(TKey, TElement>)>) that contains keys and values. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static ILookup ToLookup( 
            this ParallelQuery source, Func keySelector)
        { 
            return ToLookup(source, keySelector, EqualityComparer.Default);
        }

        ///  
        /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified
        /// key selector function and key comparer. 
        ///  
        /// The type of elements of .
        /// The type of the key returned by . 
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from.
        /// A function to extract a key from each element.
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        /// A Lookup<(Of <(TKey, TElement>)>) that contains keys and values. 
        /// 
        ///  or  or is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            // comparer may be null. In that case, GroupBy will use the default comparer.
            ParallelQuery> groupings = source.GroupBy(keySelector, comparer);
 
            Parallel.Lookup lookup = new Parallel.Lookup(comparer);
 
            Contract.Assert(groupings is QueryOperator>); 
            QueryOperator> op = groupings as QueryOperator>;
 
            IEnumerator> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);

            using(input)
            { 
                while (input.MoveNext())
                { 
                    lookup.Add(input.Current); 
                }
            } 

            return lookup;
        }
 
        /// 
        /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to specified 
        /// key selector and element selector functions. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// The type of the value returned by .
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from.
        /// A function to extract a key from each element. 
        /// 
        /// A transform function to produce a result element value from each element. 
        ///  
        /// 
        /// A Lookup<(Of <(TKey, TElement>)>) that contains values of type TElement 
        /// selected from the input sequence.
        /// 
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, Func elementSelector) 
        {
            return ToLookup(source, keySelector, elementSelector, EqualityComparer.Default); 
        } 

        ///  
        /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to
        /// a specified key selector function, a comparer and an element selector function.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// The type of the value returned by . 
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from. 
        /// A function to extract a key from each element.
        ///  
        /// A transform function to produce a result element value from each element.
        /// 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        ///  
        /// A Lookup<(Of <(TKey, TElement>)>) that contains values of type TElement selected
        /// from the input sequence. 
        ///  
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            // comparer may be null. In that case, GroupBy will use the default comparer. 
            ParallelQuery> groupings = source.GroupBy(keySelector, elementSelector, comparer); 

            Parallel.Lookup lookup = new Parallel.Lookup(comparer); 

            Contract.Assert(groupings is QueryOperator>);
            QueryOperator> op = groupings as QueryOperator>;
 
            IEnumerator> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
 
            using(input) 
            {
                while (input.MoveNext()) 
                {
                    lookup.Add(input.Current);
                }
            } 

            return lookup; 
        } 

        /*=================================================================================== 
         * MISCELLANEOUS OPERATORS
         *===================================================================================*/

        //----------------------------------------------------------------------------------- 
        // Reverses the input.
        // 
 
        /// 
        /// Inverts the order of the elements in a parallel sequence. 
        /// 
        /// The type of the elements of .
        /// A sequence of values to reverse.
        /// A sequence whose elements correspond to those of the input sequence in reverse order. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery Reverse(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new ReverseQueryOperator(source);
        }
 
        //-----------------------------------------------------------------------------------
        // Both OfType and Cast convert a weakly typed stream to a strongly typed one: 
        // the difference is that OfType filters out elements that aren't of the given type, 
        // while Cast forces the cast, possibly resulting in InvalidCastExceptions.
        // 

        /// 
        /// Filters the elements of a ParallelQuery based on a specified type.
        ///  
        /// The type to filter the elements of the sequence on.
        /// The sequence whose elements to filter. 
        /// A sequence that contains elements from the input sequence of type . 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery OfType(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            return source.OfType(); 
        } 

        ///  
        /// Converts the elements of a ParallelQuery to the specified type.
        /// 
        /// The type to convert the elements of  to.
        /// The sequence that contains the elements to be converted. 
        /// 
        /// A sequence that contains each element of the source sequence converted to the specified type. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Cast(this ParallelQuery source)
        {
            return source.Cast(); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Helper method used by First, FirstOrDefault, Last, LastOrDefault, Single, and
        // SingleOrDefault below.  This takes a query operator, gets the first item (and 
        // either checks or asserts there is at most one item in the source), and returns it.
        // If there are no elements, the method either throws an exception or, if
        // defaultIfEmpty is true, returns a default value.
        // 
        // Arguments:
        //     queryOp        - the query operator to enumerate (for the single element) 
        //     throwIfTwo     - whether to throw an exception (true) or assert (false) that 
        //                      there is no more than one element in the source
        //     defaultIfEmpty - whether to return a default value (true) or throw an 
        //                      exception if the output of the query operator is empty
        //

        private static TSource GetOneWithPossibleDefault( 
            QueryOperator queryOp, bool throwIfTwo, bool defaultIfEmpty)
        { 
            Contract.Assert(queryOp != null, "expected query operator"); 

            using (IEnumerator e = queryOp.GetEnumerator(ParallelMergeOptions.FullyBuffered)) 
            {
                if (e.MoveNext())
                {
                    TSource current = e.Current; 

                    // Some operators need to do a runtime, retail check for more than one element. 
                    // Others can simply ----sert that there was only one. 
                    if (throwIfTwo)
                    { 
                        if (e.MoveNext())
                        {
                            throw new InvalidOperationException(SR.GetString(SR.MoreThanOneMatch));
                        } 
                    }
                    else 
                    { 
                        Contract.Assert(!e.MoveNext(), "expected only a single element");
                    } 

                    return current;
                }
            } 

            if (defaultIfEmpty) 
            { 
                return default(TSource);
            } 
            else
            {
                throw new InvalidOperationException(SR.GetString(SR.NoElements));
            } 
        }
 
        //----------------------------------------------------------------------------------- 
        // First simply returns the first element from the data source; if the predicate
        // overload is used, the first element satisfying the predicate is returned. 
        // An exception is thrown for empty data sources. Alternatively, the FirstOrDefault
        // method can be used which returns defualt(T) if empty (or no elements satisfy the
        // predicate).
        // 

        ///  
        /// Returns the first element of a parallel sequence. 
        /// The type of the elements of .
        /// The sequence to return the first element of. 
        /// The first element in the specified sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource First(this ParallelQuery source)
        { 
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the 0th element.
            if (source == null) throw new ArgumentNullException("source"); 

            FirstQueryOperator queryOp = new FirstQueryOperator(source, null);

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
                    .First();
            } 

            return GetOneWithPossibleDefault(queryOp, false, false); 
        } 

        ///  
        /// Returns the first element in a parallel sequence that satisfies a specified condition.
        /// 
        /// There's a temporary difference from LINQ to Objects, this does not throw
        /// ArgumentNullException when the predicate is null. 
        /// The type of the elements of .
        /// The sequence to return an element from. 
        /// A function to test each element for a condition. 
        /// The first element in the sequence that passes the test in the specified predicate function.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// No element in  satisfies the condition in . 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static TSource First(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 
 
            FirstQueryOperator queryOp = new FirstQueryOperator(source, predicate);
 
            // If in conservative mode and a premature merge would be inserted by the First operator,
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
                    .First(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState)); 
            }

            return GetOneWithPossibleDefault(queryOp, false, false);
 
        }
 
        ///  
        /// Returns the first element of a parallel sequence, or a default value if the
        /// sequence contains no elements. 
        /// 
        /// The type of the elements of .
        /// The sequence to return the first element of.
        ///  
        /// default(TSource) if  is empty; otherwise, the first element in .
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource FirstOrDefault(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // @PERF: optimize for seekable data sources.  E.g. if an array, we can
            //     seek directly to the 0th element.
            FirstQueryOperator queryOp = new FirstQueryOperator(source, null); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially. 
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks,
                    settings.CancellationState).FirstOrDefault(); 
            } 

            return GetOneWithPossibleDefault(queryOp, false, true); 
        }

        /// 
        /// Returns the first element of the parallel sequence that satisfies a condition or a 
        /// default value if no such element is found.
        ///  
        /// There's a temporary difference from LINQ to Objects, this does not throw 
        /// ArgumentNullException when the predicate is null.
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition.
        /// 
        /// default(TSource) if  is empty or if no element passes the test 
        /// specified by predicate; otherwise, the first element in  that
        /// passes the test specified by predicate. 
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TSource FirstOrDefault(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");

            FirstQueryOperator queryOp = new FirstQueryOperator(source, predicate); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially. 
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(
                    childWithCancelChecks, settings.CancellationState) 
                    .FirstOrDefault(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState)); 
            }
 
            return GetOneWithPossibleDefault(queryOp, false, true);
        }

        //------------------------------------------------------------------------------------ 
        // Last simply returns the last element from the data source; if the predicate
        // overload is used, the last element satisfying the predicate is returned. 
        // An exception is thrown for empty data sources. Alternatively, the LastOrDefault 
        // method can be used which returns defualt(T) if empty (or no elements satisfy the
        // predicate). 
        //

        /// 
        /// Returns the last element of a parallel sequence. 
        /// The type of the elements of .
        /// The sequence to return the last element from. 
        /// The value at the last position in the source sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TSource Last(this ParallelQuery source)
        {
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the last element.
            if (source == null) throw new ArgumentNullException("source"); 
 
            LastQueryOperator queryOp = new LastQueryOperator(source, null);
 
            // If in conservative mode and a premature merge would be inserted by the First operator,
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            { 
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).Last(); 
            }

            return GetOneWithPossibleDefault(queryOp, false, false);
        } 

        ///  
        /// Returns the last element of a parallel sequence that satisfies a specified condition. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition.
        /// 
        /// The last element in the sequence that passes the test in the specified predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// No element in  satisfies the condition in .
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TSource Last(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            LastQueryOperator queryOp = new LastQueryOperator(source, predicate);
 
            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable( 
                    childWithCancelChecks, settings.CancellationState) 
                    .Last(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState));
            } 

            return GetOneWithPossibleDefault(queryOp, false, false);
        }
 
        /// 
        /// Returns the last element of a parallel sequence, or a default value if the 
        /// sequence contains no elements. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// 
        /// default() if the source sequence is empty; otherwise, the last element in the sequence.
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource LastOrDefault(this ParallelQuery source)
        { 
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the last element.
            if (source == null) throw new ArgumentNullException("source"); 

            LastQueryOperator queryOp = new LastQueryOperator(source, null);

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            { 
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).LastOrDefault();
            } 

            return GetOneWithPossibleDefault(queryOp, false, true); 
        } 

        ///  
        /// Returns the last element of a parallel sequence that satisfies a condition, or
        /// a default value if no such element is found.
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition. 
        ///  
        /// default() if the sequence is empty or if no elements pass the test in the
        /// predicate function; otherwise, the last element that passes the test in the predicate function. 
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TSource LastOrDefault(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            LastQueryOperator queryOp = new LastQueryOperator(source, predicate); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(
                    childWithCancelChecks, settings.CancellationState) 
                    .LastOrDefault(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState));
            }

            return GetOneWithPossibleDefault(queryOp, false, true); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Single yields the single element matching the optional predicate, or throws an
        // exception if there is zero or more than one match. SingleOrDefault is similar 
        // except that it returns the default value in this condition.
        //

        ///  
        /// Returns the only element of a parallel sequence, and throws an exception if there is not
        /// exactly one element in the sequence. 
        ///  
        /// The type of the elements of .
        /// The sequence to return the single element of. 
        /// The single element of the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The input sequence contains more than one element. -or- The input sequence is empty. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource Single(this ParallelQuery source)
        { 
            // @PERF: optimize for ICollection-typed data sources, i.e. we can just 
            //     check the Count property and avoid costly fork/join/synchronization.
            if (source == null) throw new ArgumentNullException("source"); 

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, null), true, false);
        }
 
        /// 
        /// Returns the only element of a parallel sequence that satisfies a specified condition, 
        /// and throws an exception if more than one such element exists. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return the single element of.
        /// A function to test an element for a condition.
        /// The single element of the input sequence that satisfies a condition.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// No element satisfies the condition in . -or- More than one element satisfies the condition in .
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource Single(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, predicate), true, false);
        } 

        ///  
        /// Returns the only element of a parallel sequence, or a default value if the sequence is 
        /// empty; this method throws an exception if there is more than one element in the sequence.
        ///  
        /// The type of the elements of .
        /// The sequence to return the single element of.
        /// 
        /// The single element of the input sequence, or default() if the 
        /// sequence contains no elements.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource SingleOrDefault(this ParallelQuery source) 
        {
            // @PERF: optimize for ICollection-typed data sources, i.e. we can just 
            //     check the Count property and avoid costly fork/join/synchronization.
            if (source == null) throw new ArgumentNullException("source");

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, null), true, true); 
        }
 
        ///  
        /// Returns the only element of a parallel sequence that satisfies a specified condition
        /// or a default value if no such element exists; this method throws an exception 
        /// if more than one element satisfies the condition.
        /// 
        /// The type of the elements of .
        /// The sequence to return the single element of. 
        /// A function to test an element for a condition.
        ///  
        /// The single element of the input sequence that satisfies the condition, or 
        /// default() if no such element is found.
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static TSource SingleOrDefault(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, predicate), true, true); 
        } 

        //----------------------------------------------------------------------------------- 
        // DefaultIfEmpty yields the data source, unmodified, if it is non-empty. Otherwise,
        // it yields a single occurrence of the default value.
        //
 
        /// 
        /// Returns the elements of the specified parallel sequence or the type parameter's 
        /// default value in a singleton collection if the sequence is empty. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return a default value for if it is empty.
        /// 
        /// A sequence that contains default(TSource) if  is empty; otherwise, .
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery DefaultIfEmpty(this ParallelQuery source)
        { 
            return DefaultIfEmpty(source, default(TSource));
        }

        ///  
        /// Returns the elements of the specified parallel sequence or the specified value
        /// in a singleton collection if the sequence is empty. 
        ///  
        /// The type of the elements of .
        /// The sequence to return the specified value for if it is empty. 
        /// The value to return if the sequence is empty.
        /// 
        /// A sequence that contains defaultValue if  is empty; otherwise, .
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery DefaultIfEmpty(this ParallelQuery source, TSource defaultValue)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DefaultIfEmptyQueryOperator(source, defaultValue);
        }
 
        //------------------------------------------------------------------------------------
        // ElementAt yields an element at a specific index.  If the data source doesn't 
        // contain such an element, an exception is thrown.  Alternatively, ElementAtOrDefault 
        // will return a default value if the given index is invalid.
        // 

        /// 
        /// Returns the element at a specified index in a parallel sequence.
        ///  
        /// The type of the elements of .
        /// A sequence to return an element from. 
        /// The zero-based index of the element to retrieve. 
        /// The element at the specified position in the source sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  is less than 0 or greater than or equal to the number of elements in . 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static TSource ElementAt(this ParallelQuery source, int index)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (index < 0) throw new ArgumentOutOfRangeException("index"); 
 
            // @PERF: there are obvious optimization opportunities for indexible data sources,
            //          since we can just seek to the element requested. 

            ElementAtQueryOperator op = new ElementAtQueryOperator(source, index);

            TSource result; 
            if (op.Aggregate(out result, false))
            { 
                return result; 
            }
 
            throw new ArgumentOutOfRangeException("index");
        }

        ///  
        /// Returns the element at a specified index in a parallel sequence or a default value if the
        /// index is out of range. 
        ///  
        /// The type of the elements of .
        /// A sequence to return an element from. 
        /// The zero-based index of the element to retrieve.
        /// 
        /// default(TSource) if the index is outside the bounds of the source sequence;
        /// otherwise, the element at the specified position in the source sequence. 
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static TSource ElementAtOrDefault(this ParallelQuery source, int index) 
        { 
            if (source == null) throw new ArgumentNullException("source");
 
            // @PERF: there are obvious optimization opportunities for indexible data sources,
            //          since we can just seek to the element requested.

            if (index >= 0) 
            {
                ElementAtQueryOperator op = new ElementAtQueryOperator(source, index); 
 
                TSource result;
                if (op.Aggregate(out result, true)) 
                {
                    return result;
                }
            } 

            return default(TSource); 
        } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// ParallelEnumerable.cs 
//
// [....] 
//
// The standard IEnumerable-based LINQ-to-Objects query provider. This class basically
// mirrors the System.Linq.Enumerable class, but (1) takes as input a special "parallel
// enumerable" data type and (2) uses an alternative implementation of the operators. 
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 
 
using System;
using System.Collections.Generic; 
using System.Threading;
using System.Diagnostics.Contracts;
using System.Linq.Parallel;
using System.Collections.Concurrent; 
using System.Collections;
using System.Threading.Tasks; 
 
namespace System.Linq
{ 
    //------------------------------------------------------------------------------------
    // Languages like C# and VB that support query comprehensions translate queries
    // into calls to a query provider which creates executable representations of the
    // query. The LINQ-to-Objects provider is implemented as a static class with an 
    // extension method per-query operator; when invoked, these return enumerable
    // objects that implement the querying behavior. 
    // 
    // We have a new sequence class for two reasons:
    // 
    //     (1) Developers can opt in to parallel query execution piecemeal, by using
    //         a special AsParallel API to wrap the data source.
    //     (2) Parallel LINQ uses a new representation for queries when compared to LINQ,
    //         which we must return from the new sequence operator implementations. 
    //
    // Comments and documentation will be somewhat light in this file. Please refer 
    // to the "official" Standard Query Operators specification for details on each API: 
    // http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/Standard_Query_Operators.doc
    // 
    // Notes:
    //     The Standard Query Operators herein should be semantically equivalent to
    //     the specification linked to above. In some cases, we offer operators that
    //     aren't available in the sequential LINQ library; in each case, we will note 
    //     why this is needed.
    // 
 
    /// 
    /// Provides a set of methods for querying objects that implement 
    /// ParallelQuery{TSource}.  This is the parallel equivalent of
    /// .
    /// 
    public static class ParallelEnumerable 
    {
        // We pass this string constant to an attribute constructor. Unfortunately, we cannot access resources from 
        // an attribute constructor, so we have to store this string in source code. 
        private const string RIGHT_SOURCE_NOT_PARALLEL_STR =
            "The second data source of a binary operator must be of type System.Linq.ParallelQuery rather than " 
            + "System.Collections.Generic.IEnumerable. To fix this problem, use the AsParallel() extension method "
            + "to convert the right data source to System.Linq.ParallelQuery.";

        //----------------------------------------------------------------------------------- 
        // Converts any IEnumerable into something that can be the target of parallel
        // query execution. 
        // 
        // Arguments:
        //     source              - the enumerable data source 
        //     options             - query analysis options to override the defaults
        //     degreeOfParallelism - the DOP to use instead of the system default, if any
        //
        // Notes: 
        //     If the argument is already a parallel enumerable, such as a query operator,
        //     no new objects are allocated. Otherwise, a very simple wrapper is instantiated 
        //     that exposes the IEnumerable as a ParallelQuery. 
        //
 
        /// 
        /// Enables parallelization of a query.
        /// 
        /// The type of elements of . 
        /// An 
        /// to convert to a . 
        /// The source as a  to bind to 
        /// ParallelEnumerable extension methods.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery AsParallel(this IEnumerable source)
        { 
            if (source == null)
            { 
                throw new ArgumentNullException("source"); 
            }
 
            return new ParallelEnumerableWrapper(source);
        }

        ///  
        /// Enables parallelization of a query, as sourced by a partitioner
        /// responsible for splitting the input sequence into partitions. 
        ///  
        /// The type of elements of .
        /// A partitioner over the input sequence. 
        /// The  as a ParallelQuery to bind to ParallelEnumerable extension methods.
        /// 
        /// The source partitioner's GetOrderedPartitions method is used when ordering is enabled,
        /// whereas the partitioner's GetPartitions is used if ordering is not enabled (the default). 
        /// The source partitioner's GetDynamicPartitions and GetDynamicOrderedPartitions are not used.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery AsParallel(this Partitioner source)
        {
            if (source == null)
            { 
                throw new ArgumentNullException("source");
            } 
 
            return new PartitionerQueryOperator(source);
        } 


        /// 
        /// Enables treatment of a data source as if it was ordered, overriding the default of unordered. 
        /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
        /// and ParallelEnumerable.Repeat. 
        ///  
        /// The type of elements of .
        /// The input sequence. 
        /// 
        /// Thrown if  is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// A natural tension exists between performance and preserving order in parallel processing. By default,
        /// a parallelized query behaves as if the ordering of the results is arbitrary 
        /// unless AsOrdered is applied or there is an explicit OrderBy operator in the query.
        /// 
        /// The source sequence which will maintain ordering in the query.
        public static ParallelQuery AsOrdered(this ParallelQuery source) 
        {
            if (source == null) 
            { 
                throw new ArgumentNullException("source");
            } 

            if (!(source is ParallelEnumerableWrapper || source is IParallelPartitionable))
            {
                PartitionerQueryOperator partitionerOp = source as PartitionerQueryOperator; 
                if (partitionerOp != null)
                { 
                    if (!partitionerOp.Orderable) 
                    {
                        throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_PartitionerNotOrderable)); 
                    }
                }
                else
                { 
                    throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidAsOrderedCall));
                } 
            } 

            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(source), true); 
        }

        /// 
        /// Enables treatment of a data source as if it was ordered, overriding the default of unordered. 
        /// AsOrdered may only be invoked on sequences returned by AsParallel, ParallelEnumerable.Range,
        /// and ParallelEnumerable.Repeat. 
        ///  
        /// The input sequence.
        ///  
        /// Thrown if the  is not one of AsParallel, ParallelEnumerable.Range, or ParallelEnumerable.Repeat.
        /// 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// A natural tension exists between performance and preserving order in parallel processing. By default, 
        /// a parallelized query behaves as if the ordering of the results is arbitrary unless AsOrdered
        /// is applied or there is an explicit OrderBy operator in the query. 
        /// 
        /// The source sequence which will maintain ordering in the query.
        public static ParallelQuery AsOrdered(this ParallelQuery source)
        { 
            if (source == null)
            { 
                throw new ArgumentNullException("source"); 
            }
 
            ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
            if (wrapper == null)
            {
                throw new InvalidOperationException(SR.GetString(SR.ParallelQuery_InvalidNonGenericAsOrderedCall)); 
            }
 
            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(wrapper), true); 
        }
 
        /// 
        /// Allows an intermediate query to be treated as if no ordering is implied among the elements.
        /// 
        ///  
        /// AsUnordered may provide
        /// performance benefits when ordering is not required in a portion of a query. 
        ///  
        /// The type of elements of .
        /// The input sequence. 
        /// The source sequence with arbitrary order.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery AsUnordered(this ParallelQuery source)
        { 
            if (source == null) 
            {
                throw new ArgumentNullException("source"); 
            }

            return new OrderingQueryOperator(QueryOperator.AsQueryOperator(source), false);
        } 

        ///  
        /// Enables parallelization of a query. 
        /// 
        /// An  to convert 
        /// to a .
        /// 
        /// The source as a ParallelQuery to bind to
        /// ParallelEnumerable extension methods. 
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery AsParallel(this IEnumerable source) 
        {
            if (source == null) throw new ArgumentNullException("source");

            return new ParallelEnumerableWrapper(source); 
        }
 
 
        //-----------------------------------------------------------------------------------
        // Converts a parallel enumerable into something that forces sequential execution. 
        //
        // Arguments:
        //     source - the parallel enumerable data source
        // 

        ///  
        /// Converts a  into an 
        ///  to force sequential
        /// evaluation of the query. 
        /// 
        /// The type of elements of .
        /// A  to convert to an .
        /// The source as an  
        /// to bind to sequential extension methods.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static IEnumerable AsSequential(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");

            // Ditch the wrapper, if there is one. 
            ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
            if (wrapper != null) 
            { 
                return wrapper.WrappedEnumerable;
            } 
            else
            {
                return source;
            } 
        }
 
 
        /// 
        /// Sets the task scheduler to execute the query. 
        /// 
        /// The type of elements of .
        /// A ParallelQuery on which to set the task scheduler option.
        /// Task scheduler to execute the query. 
        /// ParallelQuery representing the same query as source, but with the task scheduler option set.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// WithTaskScheduler is used multiple times in the query.
        /// 
        internal static ParallelQuery WithTaskScheduler(this ParallelQuery source, TaskScheduler taskScheduler)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (taskScheduler == null) throw new ArgumentNullException("taskScheduler"); 
 
            QuerySettings settings = QuerySettings.Empty;
            settings.TaskScheduler = taskScheduler; 

            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        } 

        ///  
        /// Sets the degree of parallelism to use in a query. Degree of parallelism is the maximum number of concurrently 
        /// executing tasks that will be used to process the query.
        ///  
        /// The type of elements of .
        /// A ParallelQuery on which to set the limit on the degrees of parallelism.
        /// The degree of parallelism for the query.
        /// ParallelQuery representing the same query as source, with the limit on the degrees of parallelism set. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// WithDegreeOfParallelism is used multiple times in the query. 
        /// 
        /// 
        ///  is less than 1 or greater than 63.
        ///  
        public static ParallelQuery WithDegreeOfParallelism(this ParallelQuery source, int degreeOfParallelism)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (degreeOfParallelism < 1 || degreeOfParallelism > Scheduling.MAX_SUPPORTED_DOP)
            { 
                throw new ArgumentOutOfRangeException("degreeOfParallelism");
            }

            QuerySettings settings = QuerySettings.Empty; 
            settings.DegreeOfParallelism = degreeOfParallelism;
 
            return new QueryExecutionOption( 
                QueryOperator.AsQueryOperator(source), settings);
        } 

        /// 
        /// Sets the  to associate with the query.
        ///  
        /// The type of elements of .
        /// A ParallelQuery on which to set the option. 
        /// A cancellation token. 
        /// ParallelQuery representing the same query as source, but with the 
        /// registered. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// WithCancellation is used multiple times in the query.
        ///  
        ///  
        /// The  associated with the  has been disposed.
        ///  
        public static ParallelQuery WithCancellation(this ParallelQuery source, CancellationToken cancellationToken)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            // also a convenience check whether the cancellationTokenSource backing the token is already disposed.
            // do this via a dummy registration as there is no public IsDipsosed property on CT. 
            CancellationTokenRegistration dummyRegistration = new CancellationTokenRegistration(); 
            try
            { 
                dummyRegistration = cancellationToken.Register(() => { });
            }
            catch (ObjectDisposedException)
            { 
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithCancellation_TokenSourceDisposed), "cancellationToken");
            } 
            finally 
            {
                dummyRegistration.Dispose(); 
            }

            QuerySettings settings = QuerySettings.Empty;
            settings.CancellationState = new CancellationState(cancellationToken); 

            return new QueryExecutionOption( 
                QueryOperator.AsQueryOperator(source), settings); 
        }
 
        /// 
        /// Sets the execution mode of the query.
        /// 
        /// The type of elements of . 
        /// A ParallelQuery on which to set the option.
        /// The mode in which to execute the query. 
        /// ParallelQuery representing the same query as source, but with the 
        ///  registered.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  is not a valid  value. 
        /// 
        ///  
        /// WithExecutionMode is used multiple times in the query. 
        /// 
        public static ParallelQuery WithExecutionMode(this ParallelQuery source, ParallelExecutionMode executionMode) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (executionMode != ParallelExecutionMode.Default && executionMode != ParallelExecutionMode.ForceParallelism)
            { 
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithQueryExecutionMode_InvalidMode));
            } 
 
            QuerySettings settings = QuerySettings.Empty;
            settings.ExecutionMode = executionMode; 

            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        } 

        ///  
        /// Sets the merge options for this query, which specify how the query will buffer output. 
        /// 
        /// The type of elements of . 
        /// A ParallelQuery on which to set the option.
        /// The merge optiosn to set for this query.
        /// ParallelQuery representing the same query as source, but with the
        ///  registered. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  is not a valid  value. 
        /// 
        /// 
        /// WithMergeOptions is used multiple times in the query.
        ///  
        public static ParallelQuery WithMergeOptions(this ParallelQuery source, ParallelMergeOptions mergeOptions)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (mergeOptions != ParallelMergeOptions.Default
                && mergeOptions != ParallelMergeOptions.AutoBuffered 
                && mergeOptions != ParallelMergeOptions.NotBuffered
                && mergeOptions != ParallelMergeOptions.FullyBuffered)
            {
                throw new ArgumentException(SR.GetString(SR.ParallelEnumerable_WithMergeOptions_InvalidOptions)); 
            }
 
            QuerySettings settings = QuerySettings.Empty; 
            settings.MergeOptions = mergeOptions;
 
            return new QueryExecutionOption(
                QueryOperator.AsQueryOperator(source), settings);
        }
 
        //-----------------------------------------------------------------------------------
        // Range generates a sequence of numbers that can be used as input to a query. 
        // 

        ///  
        /// Generates a parallel sequence of integral numbers within a specified range.
        /// 
        /// The value of the first integer in the sequence.
        /// The number of sequential integers to generate. 
        /// An IEnumerable<Int32> in C# or IEnumerable(Of Int32) in
        /// Visual Basic that contains a range of sequential integral numbers. 
        ///  
        ///  is less than 0
        /// -or- 
        ///  +  - 1 is larger than .
        /// 
        public static ParallelQuery Range(int start, int count)
        { 
            if (count < 0 || (count > 0 && Int32.MaxValue - (count - 1) < start)) throw new ArgumentOutOfRangeException("count");
            return new RangeEnumerable(start, count); 
        } 

        //------------------------------------------------------------------------------------ 
        // Repeat just generates a sequence of size 'count' containing 'element'.
        //

        ///  
        /// Generates a parallel sequence that contains one repeated value.
        ///  
        /// The type of the value to be repeated in the result sequence. 
        /// The value to be repeated.
        /// The number of times to repeat the value in the generated sequence. 
        /// A sequence that contains a repeated value.
        /// 
        ///  is less than 0.
        ///  
        public static ParallelQuery Repeat(TResult element, int count)
        { 
            if (count < 0) throw new ArgumentOutOfRangeException("count"); 

            return new RepeatEnumerable(element, count); 
        }

        //-----------------------------------------------------------------------------------
        // Returns an always-empty sequence. 
        //
 
        ///  
        /// Returns an empty ParallelQuery{TResult} that has the specified type argument.
        ///  
        /// The type to assign to the type parameter of the returned
        /// generic sequence.
        /// An empty sequence whose type argument is .
        public static ParallelQuery Empty() 
        {
            return System.Linq.Parallel.EmptyEnumerable.Instance; 
        } 

        //------------------------------------------------------------------------------------ 
        // A new query operator that allows an arbitrary user-specified "action" to be
        // tacked on to the query tree. The action will be invoked for every element in the
        // underlying data source, avoiding a costly final merge in the query's execution,
        // which can lead to much better scalability. The caveat is that these occur in 
        // parallel, so the user providing an action must take care to eliminate shared state
        // accesses or to synchronize as appropriate. 
        // 
        // Arguments:
        //     source  - the data source over which the actions will be invoked 
        //     action  - a delegate representing the per-element action to be invoked
        //
        // Notes:
        //     Neither source nor action may be null, otherwise this method throws. 
        //
 
        ///  
        /// Invokes in parallel the specified action for each element in the .
        ///  
        /// 
        /// This is an efficient way to process the output from a parallelized query because it does
        /// not require a merge step at the end.  However, order of execution is non-deterministic.
        ///  
        /// The type of elements of .
        /// The  whose elements will be processed by 
        /// . 
        /// An Action to invoke on each element.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static void ForAll(this ParallelQuery source, Action action) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (action == null) throw new ArgumentNullException("action");
 
            // We just instantiate the forall operator and invoke it synchronously on this thread.
            // By the time it returns, the entire query has been executed and the actions run.. 
            new ForAllOperator(source, action).RunSynchronously(); 
        }
 


        /*====================================================================================
         * BASIC OPERATORS 
         *===================================================================================*/
 
        //----------------------------------------------------------------------------------- 
        // Where is an operator that filters any elements from the data source for which the
        // user-supplied predictate returns false. 
        //

        /// 
        /// Filters in parallel a sequence of values based on a predicate. 
        /// 
        /// The type of the elements of source. 
        /// A sequence to filter. 
        /// A function to test each element for a condition.
        /// A sequence that contains elements from the input sequence that satisfy 
        /// the condition.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Where(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new WhereQueryOperator(source, predicate);
        }

        ///  
        /// Filters in parallel a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.
        ///  
        /// The type of the elements of source. 
        /// A sequence to filter.
        /// A function to test each element for a condition. 
        /// A sequence that contains elements from the input sequence that satisfy the condition.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Where(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new IndexedWhereQueryOperator(source, predicate);
        }

        //------------------------------------------------------------------------------------ 
        // Select merely maps a selector delegate over each element in the data source.
        // 
 

        ///  
        /// Projects in parallel each element of a sequence into a new form.
        /// 
        /// The type of the elements of .
        /// The type of elements resturned by selector. 
        /// A sequence of values to invoke a transform function on.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the transform function on each 
        /// element of .
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Select(
            this ParallelQuery source, Func selector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector"); 

            return new SelectQueryOperator(source, selector); 
        }

        /// 
        /// Projects in parallel each element of a sequence into a new form by incorporating the element's index. 
        /// 
        /// The type of the elements of . 
        /// The type of elements resturned by selector. 
        /// A sequence of values to invoke a transform function on.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the transform function on each
        /// element of .
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Select( 
             this ParallelQuery source, Func selector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector");

            return new IndexedSelectQueryOperator(source, selector);
        } 

        //----------------------------------------------------------------------------------- 
        // Zip combines an outer and inner data source into a single output data stream. 
        //
 
        /// 
        /// Merges in parallel two sequences by using the specified predicate function.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the return elements. 
        /// The first sequence to zip. 
        /// The second sequence to zip.
        /// A function to create a result element from two matching elements. 
        /// 
        /// A sequence that has elements of type  that are obtained by performing
        /// resultSelector pairwise on two sequences. If the sequence lengths are unequal, this truncates
        /// to the length of the shorter sequence. 
        /// 
        ///  
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Zip( 
            this ParallelQuery first, ParallelQuery second, Func resultSelector)
        {
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            return new ZipQueryOperator(first, second, resultSelector); 
        }
 
        /// 
        /// This Zip overload should never be called.
        /// This method is marked as obsolete and always throws
        ///  when invoked. 
        /// 
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Zip with a left data source of type 
        ///  and a right data source of type . 
        /// Otherwise, the Zip operator would appear to be bind to the parallel implementation, but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Zip(
            this ParallelQuery first, IEnumerable second, Func resultSelector)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        } 
 
        //-----------------------------------------------------------------------------------
        // Join is an inner join operator, i.e. elements from outer with no inner matches 
        // will yield no results in the output data stream.
        //

        ///  
        /// Correlates in parallel the elements of two sequences based on matching keys.
        /// The default equality comparer is used to compare keys. 
        ///  
        /// The type of the elements of the first sequence.
        /// The type of the elements of the second sequence. 
        /// The type of the keys returned by the key selector functions.
        /// The type of the result elements.
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element of
        /// the first sequence. 
        /// A function to extract the join key from each element of 
        /// the second sequence.
        /// A function to create a result element from two matching elements. 
        /// A sequence that has elements of type  that are obtained by performing
        /// an inner join on two sequences.
        /// 
        ///  or  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Join( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector)
        {
            return Join(
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, null); 
        }
 
        ///  
        /// This Join overload should never be called.
        /// This method is marked as obsolete and always throws  when invoked. 
        /// 
        /// This type parameter is not used.
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage Join with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation. 
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Join(
            this ParallelQuery outer, IEnumerable inner,
            Func outerKeySelector, Func innerKeySelector,
            Func resultSelector) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        } 

        ///  
        /// Correlates in parallel the elements of two sequences based on matching keys.
        /// A specified IEqualityComparer{T} is used to compare keys.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements. 
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence.
        /// A function to extract the join key from each element
        /// of the second sequence. 
        /// A function to create a result element from two matching elements.
        /// An IEqualityComparer<(Of <(T>)>) to hash and compare keys. 
        /// A sequence that has elements of type  that are obtained by performing 
        /// an inner join on two sequences.
        ///  
        ///  or  or  or
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Join( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector, IEqualityComparer comparer) 
        {
            if (outer == null) throw new ArgumentNullException("outer"); 
            if (inner == null) throw new ArgumentNullException("inner");
            if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
            if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new JoinQueryOperator( 
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); 
        }
 
        /// 
        /// This Join overload should never be called.
        /// This method is marked as obsolete and always throws  when invoked.
        ///  
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Join with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Join operator would appear to be binding to the parallel implementation, but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Join(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector, 
            Func resultSelector, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }

        //----------------------------------------------------------------------------------- 
        // GroupJoin is an outer join operator, i.e. elements from outer with no inner matches
        // will yield results (empty lists) in the output data stream. 
        // 

        ///  
        /// Correlates in parallel the elements of two sequences based on equality of keys and groups the results.
        /// The default equality comparer is used to compare keys.
        /// 
        /// The type of the elements of the first sequence. 
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements. 
        /// The first sequence to join.
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence.
        /// A function to extract the join key from each element
        /// of the second sequence. 
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// A sequence that has elements of type  that are obtained by performing 
        /// a grouped join on two sequences.
        ///  
        ///  or  or  or
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupJoin( 
            this ParallelQuery outer, ParallelQuery inner,
            Func outerKeySelector, Func innerKeySelector, 
            Func, TResult> resultSelector) 
        {
            return GroupJoin( 
                outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
        }

        ///  
        /// This GroupJoin overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        ///  
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This type parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of GroupJoin with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector,
            Func, TResult> resultSelector)
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }
 
        ///  
        /// Correlates in parallel the elements of two sequences based on key equality and groups the results.
        /// A specified IEqualityComparer{T} is used to compare keys. 
        /// 
        /// The type of the elements of the first sequence.
        /// The type of the elements of the second sequence.
        /// The type of the keys returned by the key selector functions. 
        /// The type of the result elements.
        /// The first sequence to join. 
        /// The sequence to join to the first sequence. 
        /// A function to extract the join key from each element
        /// of the first sequence. 
        /// A function to extract the join key from each element
        /// of the second sequence.
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// An IEqualityComparer<(Of <(T>)>) to hash and compare keys.
        /// A sequence that has elements of type  that are obtained by performing 
        /// a grouped join on two sequences. 
        /// 
        ///  or  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, ParallelQuery inner, 
            Func outerKeySelector, Func innerKeySelector,
            Func, TResult> resultSelector, IEqualityComparer comparer) 
        { 
            if (outer == null) throw new ArgumentNullException("outer");
            if (inner == null) throw new ArgumentNullException("inner"); 
            if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector");
            if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            return new GroupJoinQueryOperator(outer, inner,
                outerKeySelector, innerKeySelector, resultSelector, comparer); 
        } 

        ///  
        /// This GroupJoin overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used. 
        /// This type parameter is not used.
        /// This type parameter is not used. 
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        ///  
        /// This overload exists to disallow usage of GroupJoin with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the GroupJoin operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        /// 
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery GroupJoin(
            this ParallelQuery outer, IEnumerable inner, 
            Func outerKeySelector, Func innerKeySelector, 
            Func, TResult> resultSelector, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }

        //------------------------------------------------------------------------------------ 
        // SelectMany is a kind of nested loops join. For each element in the outer data
        // source, we enumerate each element in the inner data source, yielding the result 
        // with some kind of selection routine. A few different flavors are supported. 
        //
 
        /// 
        /// Projects in parallel each element of a sequence to an IEnumerable{T}
        /// and flattens the resulting sequences into one sequence.
        ///  
        /// The type of elements of .
        /// The type of the elements of the sequence returned by selector. 
        /// A sequence of values to project. 
        /// A transform function to apply to each element.
        /// A sequence whose elements are the result of invoking the one-to-many transform 
        /// function on each element of the input sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> selector) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (selector == null) throw new ArgumentNullException("selector"); 

            return new SelectManyQueryOperator(source, selector, null, null);
        }
 
        /// 
        /// Projects in parallel each element of a sequence to an IEnumerable{T}, and flattens the resulting 
        /// sequences into one sequence. The index of each source element is used in the projected form of 
        /// that element.
        ///  
        /// The type of elements of .
        /// The type of the elements of the sequence returned by selector.
        /// A sequence of values to project.
        /// A transform function to apply to each element. 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function on each element of the input sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SelectMany(
             this ParallelQuery source, Func> selector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (selector == null) throw new ArgumentNullException("selector");
 
            return new SelectManyQueryOperator(source, null, selector, null); 
        }
 
        /// 
        /// Projects each element of a sequence to an IEnumerable{T},
        /// flattens the resulting sequences into one sequence, and invokes a result selector
        /// function on each element therein. 
        /// 
        /// The type of elements of . 
        /// The type of the intermediate elements collected by . 
        /// 
        /// A sequence of values to project. 
        /// A transform function to apply to each source element;
        /// the second parameter of the function represents the index of the source element.
        /// A function to create a result element from an element from
        /// the first sequence and a collection of matching elements from the second sequence. 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function  on each element of  and then mapping 
        /// each of those sequence elements and their corresponding source element to a result element. 
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> collectionSelector, 
            Func resultSelector)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new SelectManyQueryOperator(source, collectionSelector, null, resultSelector);
        }
 
        /// 
        /// Projects each element of a sequence to an IEnumerable{T}, flattens the resulting 
        /// sequences into one sequence, and invokes a result selector function on each element 
        /// therein. The index of each source element is used in the intermediate projected
        /// form of that element. 
        /// 
        /// The type of elements of .
        /// The type of the intermediate elements collected by
        /// . 
        /// The type of elements to return.
        /// A sequence of values to project. 
        /// A transform function to apply to each source element; 
        /// the second parameter of the function represents the index of the source element.
        /// A function to create a result element from an element from 
        /// the first sequence and a collection of matching elements from the second sequence.
        /// 
        /// A sequence whose elements are the result of invoking the one-to-many transform
        /// function  on each element of  and then mapping 
        /// each of those sequence elements and their corresponding source element to a
        /// result element. 
        ///  
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery SelectMany(
            this ParallelQuery source, Func> collectionSelector, 
            Func resultSelector)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (collectionSelector == null) throw new ArgumentNullException("collectionSelector");
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new SelectManyQueryOperator(source, null, collectionSelector, resultSelector);
        }
 
        //-----------------------------------------------------------------------------------
        // OrderBy and ThenBy establish an ordering among elements, using user-specified key 
        // selection and key comparison routines. There are also descending sort variants. 
        //
 
        /// 
        /// Sorts in parallel the elements of a sequence in ascending order according to a key.
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// To achieve a stable sort, change a query of the form: 
        /// var ordered = source.OrderBy((e) => e.k); 
        /// to instead be formed as:
        /// var ordered = source.Select((e,i) => new { E=e, I=i }).OrderBy((v) => v.i).Select((v) => v.e); 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource} whose elements are sorted 
        /// according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static OrderedParallelQuery OrderBy(
            this ParallelQuery source, Func keySelector)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 
 
            return new OrderedParallelQuery(
                new SortQueryOperator(source, keySelector, null, false)); 
        }

        /// 
        /// Sorts in parallel the elements of a sequence in ascending order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted according 
        /// to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderBy(
            this ParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery( 
                new SortQueryOperator(source, keySelector, comparer, false));
        }

        ///  
        /// Sorts in parallel the elements of a sequence in descending order according to a key.
        ///  
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for 
        /// an approach to implementing a stable sort.
        /// 
        /// The type of elements of .
        /// The type of the key returned by . 
        /// A sequence of values to order.
        /// A function to extract a key from an element. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted 
        /// descending according to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderByDescending(
            this ParallelQuery source, Func keySelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery(new SortQueryOperator(source, keySelector, null, true)); 
        }

        /// 
        /// Sorts the elements of a sequence in descending order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// A sequence of values to order. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted descending 
        /// according to a key.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery OrderByDescending(
            this ParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery( 
                new SortQueryOperator(source, keySelector, comparer, true));
        }

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence
        /// in ascending order according to a key. 
        ///  
        /// 
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than 
        /// contains elements to sort. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource} whose elements are 
        /// sorted according to a key.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static OrderedParallelQuery ThenBy(
            this OrderedParallelQuery source, Func keySelector) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, null, false));
        } 

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence in 
        /// ascending order by using a specified comparer.
        ///  
        /// 
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by . 
        /// An OrderedParallelQuery{TSource} that contains
        /// elements to sort. 
        /// A function to extract a key from an element.
        /// An IComparer{TKey} to compare keys.
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        public static OrderedParallelQuery ThenBy(
            this OrderedParallelQuery source, Func keySelector, IComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, comparer, false)); 
        } 

        ///  
        /// Performs in parallel a subsequent ordering of the elements in a sequence in
        /// descending order, according to a key.
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort.
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for 
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than contains
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static OrderedParallelQuery ThenByDescending(
            this OrderedParallelQuery source, Func keySelector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery( 
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, null, true));
        } 

        /// 
        /// Performs in parallel a subsequent ordering of the elements in a sequence in descending
        /// order by using a specified comparer. 
        /// 
        ///  
        /// In contrast to the sequential implementation, this is not a stable sort. 
        /// See the remarks for OrderBy(ParallelQuery{TSource}, Func{TSource,TKey}) for
        /// an approach to implementing a stable sort. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource} than contains 
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An IComparer{TKey} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static OrderedParallelQuery ThenByDescending( 
            this OrderedParallelQuery source, Func keySelector, IComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new OrderedParallelQuery(
                (QueryOperator)source.OrderedEnumerable.CreateOrderedEnumerable(keySelector, comparer, true));
        }
 
        //------------------------------------------------------------------------------------
        // A GroupBy operation groups inputs based on a key-selection routine, yielding a 
        // one-to-many value of key-to-elements to the consumer. 
        //
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// An OrderedParallelQuery{TSource}than contains 
        /// elements to sort. 
        /// A function to extract a key from an element.
        /// An OrderedParallelQuery{TSource}whose elements are sorted 
        /// descending according to a key.
        public static ParallelQuery> GroupBy(
            this ParallelQuery source, Func keySelector)
        { 
            return GroupBy(source, keySelector, null);
        } 
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function and compares the keys by using a specified comparer. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by >.
        /// An OrderedParallelQuery{TSource} than contains 
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// An IComparer{TSource} to compare keys. 
        /// An OrderedParallelQuery{TSource} whose elements are sorted
        /// descending according to a key. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
 
            return new GroupByQueryOperator(source, keySelector, null, comparer);
        }

        ///  
        /// Groups in parallel the elements of a sequence according to a specified key selector function and
        /// projects the elements for each group by using a specified function. 
        ///  
        /// The type of elements of .
        /// The type of the key returned by . 
        /// The type of the elements in the IGrouping
        /// An OrderedParallelQuery<(Of <(TElement>)>) than contains
        /// elements to sort.
        /// A function to extract a key from an element. 
        /// A function to map each source element to an element in an  IGrouping.
        /// A ParallelQuery<IGrouping<TKey, TElement>> in C# or 
        /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping 
        /// generic object contains a collection of objects of type  and a key.
        ///  
        ///  or  or
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector)
        { 
            return GroupBy(source, keySelector, elementSelector, null); 
        }
 
        /// 
        /// Groups in parallel the elements of a sequence according to a key selector function.
        /// The keys are compared by using a comparer and each group's elements are projected by
        /// using a specified function. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by . 
        /// The type of the elements in the IGrouping
        /// An OrderedParallelQuery{TSource}than contains elements to sort. 
        /// A function to extract a key from an element.
        /// A function to map each source element to an element in an  IGrouping.
        /// An IComparer{TSource} to compare keys.
        ///  
        /// A ParallelQuery{IGrouping{TKey, TElement}} in C# or
        /// ParallelQuery(Of IGrouping(Of TKey, TElement)) in Visual Basic where each IGrouping 
        /// generic object contains a collection of objects of type  and a key. 
        /// 
        ///  
        ///  or  or
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery> GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            return new GroupByQueryOperator(source, keySelector, elementSelector, comparer);
        }
 
        //
        // @PERF: We implement the GroupBy overloads that accept a resultSelector using a GroupBy followed by a Select. This 
        // adds some extra overhead, perhaps the most significant of which is an extra delegate invocation per element. 
        //
        // One possible solution is to create two different versions of the GroupByOperator class, where one has a TResult 
        // generic type and the other does not. Since this results in code duplication, we will avoid doing that for now.
        //
        // Another possible solution is to only have the more general GroupByOperator. Unfortunately, implementing the less
        // general overload (TResult == TElement) using the more general overload would likely result in unnecessary boxing 
        // and unboxing of each processed element in the cases where TResult is a value type, so that solution comes with
        // a significant cost, too. 
        // 

        ///  
        /// Groups in parallel the elements of a sequence according to a specified
        /// key selector function and creates a result value from each group and its key.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to create a result value from each group. 
        /// A collection of elements of type  where each element represents a
        /// projection over a group and its key.
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery GroupBy( 
            this ParallelQuery source, Func keySelector, Func, TResult> resultSelector)
 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");

            return source.GroupBy(keySelector) 
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); });
        } 
 
        /// 
        /// Groups in parallel the elements of a sequence according to a specified key selector function 
        /// and creates a result value from each group and its key. The keys are compared
        /// by using a specified comparer.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to create a result value from each group. 
        /// An IEqualityComparer{TKey} to compare keys.
        /// 
        /// An ParallelQuery<IGrouping<TKey, TResult>> in C# or
        /// ParallelQuery(Of IGrouping(Of TKey, TResult)) in Visual Basic where each 
        /// IGrouping<(Of <(TKey, TResult>)>) object contains a collection of objects
        /// of type  and a key. 
        ///  
        /// 
        ///  or  or 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery GroupBy(
            this ParallelQuery source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 
 
            return source.GroupBy(keySelector, comparer).Select, TResult>(
                delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); }); 
        }

        /// 
        /// Groups in parallel the elements of a sequence according to a specified key 
        /// selector function and creates a result value from each group and its key.
        /// The elements of each group are projected by using a specified function. 
        ///  
        /// The type of the elements of .
        /// The type of the key returned by . 
        /// The type of the elements in each
        /// IGrouping{TKey, TElement}.
        /// The type of the result value returned by .
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to map each source element to an element in an 
        /// IGrouping<TKey, TElement>. 
        /// A function to create a result value from each group.
        /// A collection of elements of type  where each element represents a 
        /// projection over a group and its key.
        /// 
        ///  or  or
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery GroupBy( 
            this ParallelQuery source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) 
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return source.GroupBy(keySelector, elementSelector)
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); });
        } 

        ///  
        /// Groups the elements of a sequence according to a specified key selector function and 
        /// creates a result value from each group and its key. Key values are compared by using a
        /// specified comparer, and the elements of each group are projected by using a specified function. 
        /// 
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the elements in each 
        /// IGrouping{TKey, TElement}.
        /// The type of the result value returned by . 
        /// A sequence whose elements to group. 
        /// A function to extract the key for each element.
        /// A function to map each source element to an element in an 
        /// IGrouping{Key, TElement}.
        /// A function to create a result value from each group.
        /// An IEqualityComparer{TKey} to compare keys.
        /// A collection of elements of type  where each element represents a 
        /// projection over a group and its key.
        ///  
        ///  or  or 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery GroupBy(
            this ParallelQuery source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer)
        {
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return source.GroupBy(keySelector, elementSelector, comparer) 
                .Select, TResult>(delegate(IGrouping grouping) { return resultSelector(grouping.Key, grouping); }); 
        }
 
        /*====================================================================================
         * AGGREGATION OPERATORS
         *===================================================================================*/
 
        //-----------------------------------------------------------------------------------
        // Internal helper method that constructs an aggregation query operator and performs 
        // the actual execution/reduction before returning the result. 
        //
        // Arguments: 
        //     source  - the data source over which aggregation is performed
        //     reduce  - the binary reduction operator
        //     options - whether the operator is associative, commutative, both, or neither
        // 
        // Return Value:
        //     The result of aggregation. 
        // 

        private static T PerformAggregation(this ParallelQuery source, 
            Func reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
        {
            Contract.Assert(source != null);
            Contract.Assert(reduce != null); 
            Contract.Assert(Enum.IsDefined(typeof(QueryAggregationOptions), options), "enum is out of range");
 
            AssociativeAggregationOperator op = new AssociativeAggregationOperator( 
                source, seed, null, seedIsSpecified, reduce, reduce, delegate(T obj) { return obj; }, throwIfEmpty, options);
            return op.Aggregate(); 
        }


        ///  
        /// Run an aggregation sequentially. If the user-provided reduction function throws an exception, wrap
        /// it with an AggregateException. 
        ///  
        /// 
        ///  
        /// 
        /// if true, use the seed provided in the method argument
        /// if false, use the first element of the sequence as the seed instead
        ///  
        /// 
        private static TAccumulate PerformSequentialAggregation( 
            this ParallelQuery source, TAccumulate seed, bool seedIsSpecified, Func func) 
        {
            Contract.Assert(source != null); 
            Contract.Assert(func != null);
            Contract.Assert(seedIsSpecified || typeof(TSource) == typeof(TAccumulate));

            using(IEnumerator enumerator = source.GetEnumerator()) 
            {
                TAccumulate acc; 
                if (seedIsSpecified) 
                {
                    acc = seed; 
                }
                else
                {
                    // Take the first element as the seed 
                    if (!enumerator.MoveNext())
                    { 
                        throw new InvalidOperationException(SR.GetString(SR.NoElements)); 
                    }
 
                    acc = (TAccumulate)(object)enumerator.Current;
                }

                while (enumerator.MoveNext()) 
                {
                    TSource elem = enumerator.Current; 
 
                    // If the user delegate throws an exception, wrap it with an AggregateException
                    try 
                    {
                        acc = func(acc, elem);
                    }
                    catch (ThreadAbortException) 
                    {
                        // Do not wrap ThreadAbortExceptions 
                        throw; 
                    }
                    catch (Exception e) 
                    {
                        throw new AggregateException(e);
                    }
                } 

                return acc; 
            } 
        }
 
        //------------------------------------------------------------------------------------
        // General purpose aggregation operators, allowing pluggable binary prefix operations.
        //
 
        /// 
        /// Applies in parallel an accumulator function over a sequence. 
        ///  
        /// The type of the elements of .
        /// A sequence to aggregate over. 
        /// An accumulator function to be invoked on each element.
        /// The final accumulator value.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static TSource Aggregate( 
            this ParallelQuery source, Func func) 
        {
            return Aggregate(source, func, QueryAggregationOptions.AssociativeCommutative); 
        }

        internal static TSource Aggregate(
            this ParallelQuery source, Func func, QueryAggregationOptions options) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (func == null) throw new ArgumentNullException("func"); 
            if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");
 
            if ((options & QueryAggregationOptions.Associative) != QueryAggregationOptions.Associative)
            {
                // Non associative aggregations must be run sequentially.  We run the query in parallel
                // and then perform the reduction over the resulting list. 
                return source.PerformSequentialAggregation(default(TSource), false, func);
            } 
            else 
            {
                // If associative, we can run this aggregation in parallel. The logic of the aggregation 
                // operator depends on whether the operator is commutative, so we also pass that information
                // down to the query planning/execution engine.
                return source.PerformAggregation(func, default(TSource), false, true, options);
            } 
        }
 
        ///  
        /// Applies in parallel an accumulator function over a sequence.
        /// The specified seed value is used as the initial accumulator value. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// A sequence to aggregate over. 
        /// The initial accumulator value.
        /// An accumulator function to be invoked on each element. 
        /// The final accumulator value. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TAccumulate Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func) 
        {
            return Aggregate(source, seed, func, QueryAggregationOptions.AssociativeCommutative);
        }
 
        internal static TAccumulate Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func, QueryAggregationOptions options) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (func == null) throw new ArgumentNullException("func"); 
            if ((~(QueryAggregationOptions.Associative | QueryAggregationOptions.Commutative) & options) != 0) throw new ArgumentOutOfRangeException("options");

            return source.PerformSequentialAggregation(seed, true, func);
        } 

        ///  
        /// Applies in parallel an accumulator function over a sequence. The specified 
        /// seed value is used as the initial accumulator value, and the specified
        /// function is used to select the result value. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// The type of the resulting value. 
        /// A sequence to aggregate over.
        /// The initial accumulator value. 
        /// An accumulator function to be invoked on each element. 
        /// A function to transform the final accumulator value
        /// into the result value. 
        /// The transformed final accumulator value.
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TResult Aggregate(
            this ParallelQuery source, TAccumulate seed, Func func,
            Func resultSelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (func == null) throw new ArgumentNullException("func"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");
 
            TAccumulate acc = source.PerformSequentialAggregation(seed, true, func);
            try
            {
                return resultSelector(acc); 
            }
            catch (ThreadAbortException) 
            { 
                // Do not wrap ThreadAbortExceptions
                throw; 
            }
            catch (Exception e)
            {
                throw new AggregateException(e); 
            }
        } 
 
        /// 
        /// Applies in parallel an accumulator function over a sequence. This overload is not 
        /// available in the sequential implementation.
        /// 
        /// 
        /// This overload is specific to processing a parallelized query. A parallelized query may 
        /// partition the data source sequence into several sub-sequences (partitions).
        /// The  is invoked on each element within partitions. 
        /// Each partition then yields a single accumulated result. The  
        /// is then invoked on the results of each partition to yield a single element. This element is then
        /// transformed by the  function. 
        /// 
        /// The type of the elements of .
        /// The type of the accumulator value.
        /// The type of the resulting value. 
        /// A sequence to aggregate over.
        /// The initial accumulator value. 
        ///  
        /// An accumulator function to be invoked on each element in a partition.
        ///  
        /// 
        /// An accumulator function to be invoked on the yielded element from each partition.
        /// 
        ///  
        /// A function to transform the final accumulator value into the result value.
        ///  
        /// The transformed final accumulator value. 
        /// 
        ///  or  
        /// or  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TResult Aggregate( 
            this ParallelQuery source, TAccumulate seed, Func updateAccumulatorFunc,
            Func combineAccumulatorsFunc, Func resultSelector)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
            if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector"); 

            return new AssociativeAggregationOperator( 
                source, seed, null, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
                false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
        }
 
        /// 
        /// Applies in parallel an accumulator function over a sequence.  This overload is not 
        /// available in the sequential implementation. 
        /// 
        ///  
        /// This overload is specific to parallelized queries. A parallelized query may partition the data source sequence
        /// into several sub-sequences (partitions). The  is invoked
        /// on each element within partitions. Each partition then yields a single accumulated result.
        /// The  
        /// is then invoked on the results of each partition to yield a single element. This element is then
        /// transformed by the  function. 
        ///  
        /// The type of the elements of .
        /// The type of the accumulator value. 
        /// The type of the resulting value.
        /// A sequence to aggregate over.
        /// 
        /// A function that returns the initial accumulator value. 
        /// 
        ///  
        /// An accumulator function to be invoked on each element in a partition. 
        /// 
        ///  
        /// An accumulator function to be invoked on the yielded element from each partition.
        /// 
        /// 
        /// A function to transform the final accumulator value into the result value. 
        /// 
        /// The transformed final accumulator value. 
        ///  
        ///  or  or 
        /// or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TResult Aggregate(
            this ParallelQuery source, 
            Func seedFactory,
            Func updateAccumulatorFunc,
            Func combineAccumulatorsFunc,
            Func resultSelector) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (seedFactory == null) throw new ArgumentNullException("seedFactory"); 
            if (updateAccumulatorFunc == null) throw new ArgumentNullException("updateAccumulatorFunc");
            if (combineAccumulatorsFunc == null) throw new ArgumentNullException("combineAccumulatorsFunc"); 
            if (resultSelector == null) throw new ArgumentNullException("resultSelector");

            return new AssociativeAggregationOperator(
                source, default(TAccumulate), seedFactory, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector, 
                false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
        } 
 

        //----------------------------------------------------------------------------------- 
        // Count and LongCount reductions.
        //

        ///  
        /// Returns the number of elements in a parallel sequence.
        ///  
        /// The type of the elements of . 
        /// A sequence that contains elements to be counted.
        /// The number of elements in the input sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// The number of elements in source is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static int Count(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
 
            // If the data source is a collection, we can just return the count right away. 
            ParallelEnumerableWrapper sourceAsWrapper = source as ParallelEnumerableWrapper;
            if (sourceAsWrapper != null) 
            {
                ICollection sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection;
                if (sourceAsCollection != null)
                { 
                    return sourceAsCollection.Count;
                } 
            } 

            // Otherwise, enumerate the whole thing and aggregate a count. 
            checked
            {
                return new CountAggregationOperator(source).Aggregate();
            } 
        }
 
        ///  
        /// Returns a number that represents how many elements in the specified
        /// parallel sequence satisfy a condition. 
        /// 
        /// The type of the elements of .
        /// A sequence that contains elements to be counted.
        /// A function to test each element for a condition. 
        /// 
        /// A number that represents how many elements in the sequence satisfy the condition 
        /// in the predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The number of elements in source is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int Count(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            // Construct a where operator to filter out unmatching elements, and then aggregate. 
            checked
            { 
                return new CountAggregationOperator(Where(source, predicate)).Aggregate();
            }
        }
 
        /// 
        /// Returns an Int64 that represents the total number of elements in a parallel sequence. 
        ///  
        /// The type of the elements of .
        /// A sequence that contains elements to be counted. 
        /// The number of elements in the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The number of elements in source is larger than . 
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long LongCount(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
 
            // If the data source is a collection, we can just return the count right away.
            ParallelEnumerableWrapper sourceAsWrapper = source as ParallelEnumerableWrapper; 
            if (sourceAsWrapper != null)
            {
                ICollection sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection;
                if (sourceAsCollection != null) 
                {
                    return sourceAsCollection.Count; 
                } 
            }
 
            // Otherwise, enumerate the whole thing and aggregate a count.
            return new LongCountAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Returns an Int64 that represents how many elements in a parallel sequence satisfy a condition. 
        ///  
        /// The type of the elements of .
        /// A sequence that contains elements to be counted. 
        /// A function to test each element for a condition.
        /// 
        /// A number that represents how many elements in the sequence satisfy the condition
        /// in the predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The number of elements in source is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static long LongCount(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");

            // Construct a where operator to filter out unmatching elements, and then aggregate. 
            return new LongCountAggregationOperator(Where(source, predicate)).Aggregate();
        } 
 
        //-----------------------------------------------------------------------------------
        // Sum aggregations. 
        //

        /// 
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// The sum is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static int Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntSumAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static int? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntSumAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new LongSumAggregationOperator(source).Aggregate();
        } 

        ///  
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than . 
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long? Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableLongSumAggregationOperator(source).Aggregate(); 
        }
 
        /// 
        /// Computes in parallel the sum of a sequence of values.
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static float Sum(this ParallelQuery source) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new FloatSumAggregationOperator(source).Aggregate(); 
        }

        /// 
        /// Computes in parallel the sum of a sequence of values. 
        /// 
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static float? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableFloatSumAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Computes in parallel the sum of a sequence of values. 
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleSumAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double? Sum(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDoubleSumAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the sum of a sequence of values.
        /// 
        /// A sequence of values to calculate the sum of.
        /// The sum of the values in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Sum(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new DecimalSumAggregationOperator(source).Aggregate();
        }

        ///  
        /// Computes in parallel the sum of a sequence of values.
        ///  
        /// A sequence of values to calculate the sum of. 
        /// The sum of the values in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Sum(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDecimalSumAggregationOperator(source).Aggregate();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static int Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        }

        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static int? Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum(); 
        }
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// The sum is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static long Sum(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Sum(); 
        }
 
        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static long? Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        }

        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Sum(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Sum(); 
        }

        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static double Sum(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Sum(); 
        }
 
        ///  
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of.
        /// A transform function to apply to each element. 
        /// The sum of the values in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static double? Sum(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Sum();
        } 

        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// The sum is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal Sum(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Sum();
        } 
 
        /// 
        /// Computes in parallel the sum of the sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values to calculate the sum of. 
        /// A transform function to apply to each element.
        /// The sum of the values in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The sum is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static decimal? Sum(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Sum();
        }
 
        //-----------------------------------------------------------------------------------
        // Helper methods used for Min/Max aggregations below. This class can create a whole 
        // bunch of type-specific delegates that are passed to the general aggregation 
        // infrastructure. All comparisons are performed using the Comparer.Default
        // comparator. LINQ doesn't offer a way to override this, so neither do we. 
        //
        // @PERF: we'll eventually want inlined primitive providers that use IL instructions
        //    for comparison instead of the Comparer.CompareTo method.
        // 

        //------------------------------------------------------------------------------------ 
        // Min aggregations. 
        //
 
        /// 
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static int Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Min(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntMinMaxAggregationOperator(source, -1).Aggregate();
        } 
 
        /// 
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static long Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new LongMinMaxAggregationOperator(source, -1).Aggregate();
        }

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long? Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableLongMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new FloatMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        /// 
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatMinMaxAggregationOperator(source, -1).Aggregate();
        }

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleMinMaxAggregationOperator(source, -1).Aggregate(); 
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDoubleMinMaxAggregationOperator(source, -1).Aggregate();
        } 

        /// 
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal Min(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalMinMaxAggregationOperator(source, -1).Aggregate(); 
        }
 
        ///  
        /// Returns the minimum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the minimum value of.
        /// The minimum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal? Min(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalMinMaxAggregationOperator(source, -1).Aggregate(); 
        } 

        ///  
        /// Returns the minimum value in a parallel sequence of values.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// The minimum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements and  is a non-nullable value type.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TSource Min(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return AggregationMinMaxHelpers.ReduceMin(source);
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static int Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        }

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value. 
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static int? Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        } 
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static long Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min();
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static long? Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min(); 
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min();
        } 
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double Min(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Min(); 
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static double? Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min();
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element.
        /// The minimum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Min(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Min(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the minimum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the minimum value of.
        /// A transform function to apply to each element. 
        /// The minimum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the minimum value. 
        /// 
        /// The type of elements of .
        /// The type of the value returned by .
        /// A sequence of values to determine the minimum value of. 
        /// A transform function to apply to each element.
        /// The minimum value in the sequence. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements and  is a non-nullable value type.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static TResult Min(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Min();
        } 

        //----------------------------------------------------------------------------------- 
        // Max aggregations. 
        //
 
        /// 
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static int Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Max(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntMinMaxAggregationOperator(source, 1).Aggregate();
        } 
 
        /// 
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static long Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new LongMinMaxAggregationOperator(source, 1).Aggregate();
        }

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long? Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableLongMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values. 
        /// 
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new FloatMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        /// 
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Max(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatMinMaxAggregationOperator(source, 1).Aggregate();
        }

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of. 
        /// The maximum value in the sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleMinMaxAggregationOperator(source, 1).Aggregate(); 
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableDoubleMinMaxAggregationOperator(source, 1).Aggregate();
        } 

        /// 
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal Max(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalMinMaxAggregationOperator(source, 1).Aggregate(); 
        }
 
        ///  
        /// Returns the maximum value in a parallel sequence of values.
        ///  
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static decimal? Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalMinMaxAggregationOperator(source, 1).Aggregate(); 
        } 

        ///  
        /// Returns the maximum value in a parallel sequence of values.
        /// 
        /// A sequence of values to determine the maximum value of.
        /// The maximum value in the sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements and  is a non-nullable value type. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TSource Max(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return AggregationMinMaxHelpers.ReduceMax(source);
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static int Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        }

        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value.
        ///  
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static int? Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static long Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max();
        }
 
        /// 
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static long? Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value.
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static float Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max(); 
        }
 
        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static float? Max(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Max();
        } 

        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        ///  contains no elements.
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static double Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max(); 
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value.
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double? Max(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Max();
        }

        ///  
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        ///  
        /// The type of elements of .
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static decimal Max(this ParallelQuery source, Func selector) 
        { 
            return source.Select(selector).Max();
        } 

        /// 
        /// Invokes in parallel a transform function on each element of a
        /// sequence and returns the maximum value. 
        /// 
        /// The type of elements of . 
        /// A sequence of values to determine the maximum value of. 
        /// A transform function to apply to each element.
        /// The maximum value in the sequence. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal? Max(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Max();
        } 

        ///  
        /// Invokes in parallel a transform function on each element of a 
        /// sequence and returns the maximum value.
        ///  
        /// The type of elements of .
        /// The type of the value returned by .
        /// A sequence of values to determine the maximum value of.
        /// A transform function to apply to each element. 
        /// The maximum value in the sequence.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements and  is a non-nullable value type.
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TResult Max(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Max();
        }
 
        //------------------------------------------------------------------------------------
        // Average aggregations. 
        // 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// The sum or count of the elements in the sequence is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new IntAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values.
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableIntAverageAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new LongAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableLongAverageAggregationOperator(source).Aggregate();
        }

        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average. 
        /// The average of the sequence of values.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new FloatAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static float? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source"); 
            return new NullableFloatAverageAggregationOperator(source).Aggregate();
        } 

        /// 
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements.
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new DoubleAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values.
        ///  
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values.
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static double? Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDoubleAverageAggregationOperator(source).Aggregate(); 
        } 

        ///  
        /// Computes in parallel the average of a sequence of values.
        /// 
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  contains no elements. 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static decimal Average(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DecimalAverageAggregationOperator(source).Aggregate();
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values. 
        ///  
        /// A sequence of values that are used to calculate an average.
        /// The average of the sequence of values. 
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static decimal? Average(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return new NullableDecimalAverageAggregationOperator(source).Aggregate(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements.
        /// 
        /// 
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static double Average(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Average(); 
        }
 
        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double? Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        }

        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        ///  contains no elements. 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than .
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static double Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        }

        ///  
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence. 
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// The sum or count of the elements in the sequence is larger than . 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double? Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average(); 
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  contains no elements. 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static float Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average();
        } 
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        /// 
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element.
        /// The average of the sequence of values. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static float? Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average(); 
        }

        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static double Average(this ParallelQuery source, Func selector)
        { 
            return source.Select(selector).Average(); 
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of .
        /// A sequence of values that are used to calculate an average. 
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static double? Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average();
        }
 
        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence. 
        /// 
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element.
        /// The average of the sequence of values.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static decimal Average(this ParallelQuery source, Func selector) 
        {
            return source.Select(selector).Average(); 
        }

        /// 
        /// Computes in parallel the average of a sequence of values that are obtained 
        /// by invoking a transform function on each element of the input sequence.
        ///  
        /// The type of elements of . 
        /// A sequence of values that are used to calculate an average.
        /// A transform function to apply to each element. 
        /// The average of the sequence of values.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static decimal? Average(this ParallelQuery source, Func selector)
        {
            return source.Select(selector).Average(); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Any returns true if there exists an element for which the predicate returns true.
        // 

        /// 
        /// Determines in parallel whether any element of a sequence satisfies a condition.
        ///  
        /// The type of elements of .
        /// An IEnumerable whose elements to apply the predicate to. 
        /// A function to test each element for a condition. 
        /// 
        /// true if any elements in the source sequence pass the test in the specified predicate; otherwise, false. 
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static bool Any(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            return new AnyAllSearchOperator(source, true, predicate).Aggregate(); 
        }
 
        /// 
        /// Determines whether a parallel sequence contains any elements.
        /// 
        /// The type of elements of . 
        /// The IEnumerable to check for emptiness.
        /// true if the source sequence contains any elements; otherwise, false. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static bool Any(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 

            IEnumerator e;

            // @PERF: if we know the count, we can just return true if it's non-zero. 

            // If the source is a query operator, shut off pipelining. 
            QueryOperator asOperator = source as QueryOperator; 
            if (asOperator != null)
            { 
                e = asOperator.GetEnumerator(ParallelMergeOptions.FullyBuffered);
            }
            else
            { 
                e = source.GetEnumerator();
            } 
 
            // If the results are non-empty, return true. Otherwise, false.
            using (e) 
            {
                if (e.MoveNext())
                {
                    return true; 
                }
            } 
 
            return false;
        } 

        //-----------------------------------------------------------------------------------
        // All returns false if there exists an element for which the predicate returns false.
        // 

        ///  
        /// Determines in parallel whether all elements of a sequence satisfy a condition. 
        /// 
        /// The type of elements of . 
        /// A sequence whose elements to apply the predicate to.
        /// A function to test each element for a condition.
        /// 
        /// true if all elements in the source sequence pass the test in the specified predicate; otherwise, false. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static bool All(this ParallelQuery source, Func predicate) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new AnyAllSearchOperator(source, false, predicate).Aggregate();
        }
 
        //------------------------------------------------------------------------------------
        // Contains returns true if the specified value was found in the data source. 
        // 

        ///  
        /// Determines in parallel whether a sequence contains a specified element
        /// by using the default equality comparer.
        /// 
        /// The type of elements of . 
        /// A sequence in which to locate a value.
        /// The value to locate in the sequence. 
        ///  
        /// true if the source sequence contains an element that has the specified value; otherwise, false.
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static bool Contains(this ParallelQuery source, TSource value)
        {
            return Contains(source, value, null);
        } 

        ///  
        /// Determines in parallel whether a sequence contains a specified element by using a 
        /// specified IEqualityComparer{T}.
        ///  
        /// The type of elements of .
        /// A sequence in which to locate a value.
        /// The value to locate in the sequence.
        /// An equality comparer to compare values. 
        /// 
        /// true if the source sequence contains an element that has the specified value; otherwise, false. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static bool Contains(this ParallelQuery source, TSource value, IEqualityComparer comparer)
        { 
            if (source == null) throw new ArgumentNullException("source");

            // @PERF: there are many simple optimizations we can make for collection types with known sizes.
 
            return new ContainsSearchOperator(source, value, comparer).Aggregate();
        } 
 
        /*===================================================================================
         * TOP (TAKE, SKIP) OPERATORS 
         *===================================================================================*/

        //-----------------------------------------------------------------------------------
        // Take will take the first [0..count) contiguous elements from the input. 
        //
 
        ///  
        /// Returns a specified number of contiguous elements from the start of a parallel sequence.
        ///  
        /// The type of elements of .
        /// The sequence to return elements from.
        /// The number of elements to return.
        ///  
        /// A sequence that contains the specified number of elements from the start of the input sequence.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Take(this ParallelQuery source, int count)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            if (count > 0)
            { 
                return new TakeOrSkipQueryOperator(source, count, true); 
            }
            else 
            {
                return ParallelEnumerable.Empty();
            }
        } 

        //----------------------------------------------------------------------------------- 
        // TakeWhile will take the first [0..N) contiguous elements, where N is the smallest 
        // index of an element for which the predicate yields false.
        // 

        /// 
        /// Returns elements from a parallel sequence as long as a specified condition is true.
        ///  
        /// The type of elements of .
        /// The sequence to return elements from. 
        /// A function to test each element for a condition. 
        /// 
        /// A sequence that contains the elements from the input sequence that occur before 
        /// the element at which the test no longer passes.
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery TakeWhile(this ParallelQuery source, Func predicate) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new TakeOrSkipWhileQueryOperator(source, predicate, null, true);
        }
 
        /// 
        /// Returns elements from a parallel sequence as long as a specified condition is true. 
        /// The element's index is used in the logic of the predicate function. 
        /// 
        /// The type of elements of . 
        /// The sequence to return elements from.
        /// 
        /// A function to test each source element for a condition; the second parameter of the
        /// function represents the index of the source element. 
        /// 
        ///  
        /// A sequence that contains elements from the input sequence that occur before 
        /// the element at which the test no longer passes.
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery TakeWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return new TakeOrSkipWhileQueryOperator(source, null, predicate, true); 
        }

        //------------------------------------------------------------------------------------
        // Skip will take the last [count..M) contiguous elements from the input, where M is 
        // the size of the input.
        // 
 
        /// 
        /// Bypasses a specified number of elements in a parallel sequence and then returns the remaining elements. 
        /// 
        /// The type of elements of .
        /// The sequence to return elements from.
        /// The number of elements to skip before returning the remaining elements. 
        /// 
        /// A sequence that contains the elements that occur after the specified index in the input sequence. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Skip(this ParallelQuery source, int count)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // If the count is 0 (or less) we just return the whole stream. 
            if (count <= 0) 
            {
                return source; 
            }

            return new TakeOrSkipQueryOperator(source, count, false);
        } 

        //----------------------------------------------------------------------------------- 
        // SkipWhile will take the last [N..M) contiguous elements, where N is the smallest 
        // index of an element for which the predicate yields false, and M is the size of
        // the input data source. 
        //

        /// 
        /// Bypasses elements in a parallel sequence as long as a specified 
        /// condition is true and then returns the remaining elements.
        ///  
        /// The type of elements of . 
        /// The sequence to return elements from.
        /// A function to test each element for a condition. 
        /// A sequence that contains the elements from the input sequence starting at
        /// the first element in the linear series that does not pass the test specified by
        /// predicate.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SkipWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return new TakeOrSkipWhileQueryOperator(source, predicate, null, false);
        } 

        ///  
        /// Bypasses elements in a parallel sequence as long as a specified condition is true and 
        /// then returns the remaining elements. The element's index is used in the logic of
        /// the predicate function. 
        /// 
        /// The type of elements of .
        /// The sequence to return elements from.
        ///  
        /// A function to test each source element for a condition; the
        /// second parameter of the function represents the index of the source element. 
        ///  
        /// 
        /// A sequence that contains the elements from the input sequence starting at the 
        /// first element in the linear series that does not pass the test specified by
        /// predicate.
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery SkipWhile(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return new TakeOrSkipWhileQueryOperator(source, null, predicate, false);
        } 

        /*==================================================================================== 
         * SET OPERATORS 
         *===================================================================================*/
 
        //------------------------------------------------------------------------------------
        // Appends the second data source to the first, preserving order in the process.
        //
 
        /// 
        /// Concatenates two parallel sequences. 
        ///  
        /// The type of the elements of the input sequences.
        /// The first sequence to concatenate. 
        /// The sequence to concatenate to the first sequence.
        /// A sequence that contains the concatenated elements of the two input sequences.
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Concat(this ParallelQuery first, ParallelQuery second) 
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 
            return new ConcatQueryOperator(first, second);
        }

        ///  
        /// This Concat overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage of Concat with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Concat operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Concat(this ParallelQuery first, IEnumerable second)
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }
 
        //----------------------------------------------------------------------------------- 
        // Compares two input streams pairwise for equality.
        // 

        /// 
        /// Determines whether two parallel sequences are equal by comparing the elements by using
        /// the default equality comparer for their type. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence to compare to second. 
        /// A sequence to compare to the first input sequence.
        ///  
        /// true if the two source sequences are of equal length and their corresponding elements
        /// are equal according to the default equality comparer for their type; otherwise, false.
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static bool SequenceEqual(this ParallelQuery first, ParallelQuery second) 
        {
            if (first == null) throw new ArgumentNullException("first"); 
            if (second == null) throw new ArgumentNullException("second"); 
            return SequenceEqual(first, second, null);
        } 

        /// 
        /// This SequenceEqual overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        /// 
        /// This type parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// Thrown every time this method is called.
        /// 
        /// This overload exists to disallow usage of SequenceEqual with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation. 
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static bool SequenceEqual(this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Determines whether two parallel sequences are equal by comparing their elements by 
        /// using a specified IEqualityComparer{T}. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence to compare to .
        /// A sequence to compare to the first input sequence.
        /// An IEqualityComparer<(Of <(T>)>) to use to compare elements.
        ///  
        /// true if the two source sequences are of equal length and their corresponding
        /// elements are equal according to the default equality comparer for their type; otherwise, false. 
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static bool SequenceEqual(this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second");

            // If comparer is null, use the default one 
            comparer = comparer ?? EqualityComparer.Default;
 
            QueryOperator leftOp = QueryOperator.AsQueryOperator(first); 
            QueryOperator rightOp = QueryOperator.AsQueryOperator(second);
 
            // We use a fully-qualified type name for Shared here to prevent the conflict between System.Linq.Parallel.Shared<>
            // and System.Threading.Shared<> in the 3.5 legacy build.
            QuerySettings settings = leftOp.SpecifiedQuerySettings.Merge(rightOp.SpecifiedQuerySettings)
                .WithDefaults() 
                .WithPerExecutionSettings(new CancellationTokenSource(), new System.Linq.Parallel.Shared(false));
 
            // If first.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException. 
            IEnumerator e1 = first.GetEnumerator();
            try 
            {
                // If second.GetEnumerator throws an exception, we don't want to wrap it with an AggregateException.
                IEnumerator e2 = second.GetEnumerator();
                try 
                {
                    while (e1.MoveNext()) 
                    { 
                        if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
                    } 
                    if (e2.MoveNext()) return false;
                }
                catch (ThreadAbortException)
                { 
                    // Do not wrap ThreadAbortExceptions
                    throw; 
                } 
                catch (Exception ex)
                { 
                    ExceptionAggregator.ThrowOCEorAggregateException(ex, settings.CancellationState);
                }
                finally
                { 
                    DisposeEnumerator(e2, settings.CancellationState);
                } 
            } 
            finally
            { 
                DisposeEnumerator(e1, settings.CancellationState);
            }

            return true; 
        }
 
        ///  
        /// A helper method for SequenceEqual to dispose an enumerator. If an exception is thrown by the disposal,
        /// it gets wrapped into an AggregateException, unless it is an OCE with the query's CancellationToken. 
        /// 
        private static void DisposeEnumerator(IEnumerator e, CancellationState cancelState)
        {
            try 
            {
                e.Dispose(); 
            } 
            catch (ThreadAbortException)
            { 
                // Do not wrap ThreadAbortExceptions
                throw;
            }
            catch (Exception ex) 
            {
                ExceptionAggregator.ThrowOCEorAggregateException(ex, cancelState); 
            } 
        }
 
        /// 
        /// This SequenceEqual overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// Thrown every time this method is called.
        /// 
        /// This overload exists to disallow usage of SequenceEqual with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the SequenceEqual operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to sequential implementation. 
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static bool SequenceEqual(this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        //------------------------------------------------------------------------------------
        // Calculates the distinct set of elements in the single input data source. 
        // 

        ///  
        /// Returns distinct elements from a parallel sequence by using the
        /// default equality comparer to compare values.
        /// 
        /// The type of the elements of . 
        /// The sequence to remove duplicate elements from.
        /// A sequence that contains distinct elements from the source sequence. 
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Distinct(
            this ParallelQuery source)
        {
            return Distinct(source, null); 
        }
 
        ///  
        /// Returns distinct elements from a parallel sequence by using a specified
        /// IEqualityComparer{T} to compare values. 
        /// 
        /// The type of the elements of .
        /// The sequence to remove duplicate elements from.
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains distinct elements from the source sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Distinct( 
            this ParallelQuery source, IEqualityComparer comparer)
        {
            if (source == null) throw new ArgumentNullException("source");
 
            return new DistinctQueryOperator(source, comparer);
        } 
 
        //-----------------------------------------------------------------------------------
        // Calculates the union between the first and second data sources. 
        //

        /// 
        /// Produces the set union of two parallel sequences by using the default equality comparer. 
        /// 
        /// The type of the elements of the input sequences. 
        /// A sequence whose distinct elements form the first set for the union. 
        /// A sequence whose distinct elements form the second set for the union.
        /// A sequence that contains the elements from both input sequences, excluding duplicates. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Union( 
            this ParallelQuery first, ParallelQuery second)
        { 
            return Union(first, second, null); 
        }
 
        /// 
        /// This Union overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Union with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Union operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Union(
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Produces the set union of two parallel sequences by using a specified IEqualityComparer{T}. 
        ///  
        /// The type of the elements of the input sequences.
        /// A sequence whose distinct elements form the first set for the union. 
        /// A sequence whose distinct elements form the second set for the union.
        /// An IEqualityComparer<(Of <(T>)>) to compare values.
        /// A sequence that contains the elements from both input sequences, excluding duplicates.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        public static ParallelQuery Union( 
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        { 
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second");

            return new UnionQueryOperator(first, second, comparer); 
        }
 
        ///  
        /// This Union overload should never be called.
        /// This method is marked as obsolete and always throws  when called. 
        /// 
        /// This type parameter is not used.
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Union with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Union operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Union( 
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }

        //-----------------------------------------------------------------------------------
        // Calculates the intersection between the first and second data sources. 
        //
 
        ///  
        /// Produces the set intersection of two parallel sequences by using the
        /// default equality comparer to compare values. 
        /// 
        /// The type of the elements of the input sequences.
        /// A sequence whose distinct elements that also appear in  will be returned. 
        /// 
        ///  
        /// A sequence whose distinct elements that also appear in the first sequence will be returned. 
        /// 
        /// A sequence that contains the elements that form the set intersection of two sequences. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Intersect( 
            this ParallelQuery first, ParallelQuery second)
        { 
            return Intersect(first, second, null); 
        }
 
        /// 
        /// This Intersect overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Intersect with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Intersect(
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /// 
        /// Produces the set intersection of two parallel sequences by using 
        /// the specified IEqualityComparer{T} to compare values. 
        /// 
        /// The type of the elements of the input sequences. 
        /// 
        /// A sequence whose distinct elements that also appear in  will be returned.
        /// 
        ///  
        /// A sequence whose distinct elements that also appear in the first sequence will be returned.
        ///  
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains the elements that form the set intersection of two sequences.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        public static ParallelQuery Intersect(
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer) 
        {
            if (first == null) throw new ArgumentNullException("first"); 
            if (second == null) throw new ArgumentNullException("second"); 

            return new IntersectQueryOperator(first, second, comparer); 
        }

        /// 
        /// This Intersect overload should never be called. 
        /// This method is marked as obsolete and always throws  when called.
        ///  
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a .
        /// The exception that occurs when this method is called.
        ///  
        /// This overload exists to disallow usage of Intersect with a left data source of type
        ///  and a right data source of type . 
        /// Otherwise, the Intersect operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Intersect(
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer)
        { 
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        } 
 
        //-----------------------------------------------------------------------------------
        // Calculates the relative complement of the first and second data sources, that is, 
        // the elements in first that are not found in second.
        //

        ///  
        /// Produces the set difference of two parallel sequences by using
        /// the default equality comparer to compare values. 
        ///  
        /// The type of the elements of the input sequences.
        ///  
        /// A sequence whose elements that are not also in  will be returned.
        /// 
        /// 
        /// A sequence whose elements that also occur in the first sequence will cause those 
        /// elements to be removed from the returned sequence.
        ///  
        /// A sequence that contains the set difference of the elements of two sequences. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Except(
            this ParallelQuery first, ParallelQuery second)
        { 
            return Except(first, second, null);
        } 
 
        /// 
        /// This Except overload should never be called. 
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used.
        /// This overload always throws a . 
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Except with a left data source of type 
        ///  and a right data source of type .
        /// Otherwise, the Except operator would appear to be binding to the parallel implementation,
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
        public static ParallelQuery Except( 
            this ParallelQuery first, IEnumerable second) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel)); 
        }

        /// 
        /// Produces the set difference of two parallel sequences by using the 
        /// specified IEqualityComparer{T} to compare values.
        ///  
        /// The type of the elements of the input sequences. 
        /// A sequence whose elements that are not also in  will be returned.
        ///  
        /// A sequence whose elements that also occur in the first sequence will cause those elements
        /// to be removed from the returned sequence.
        /// 
        /// An IEqualityComparer<(Of <(T>)>) to compare values. 
        /// A sequence that contains the set difference of the elements of two sequences.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Except( 
            this ParallelQuery first, ParallelQuery second, IEqualityComparer comparer)
        {
            if (first == null) throw new ArgumentNullException("first");
            if (second == null) throw new ArgumentNullException("second"); 

            return new ExceptQueryOperator(first, second, comparer); 
        } 

        ///  
        /// This Except overload should never be called.
        /// This method is marked as obsolete and always throws  when called.
        /// 
        /// This type parameter is not used. 
        /// This parameter is not used.
        /// This parameter is not used. 
        /// This parameter is not used. 
        /// This overload always throws a .
        /// The exception that occurs when this method is called. 
        /// 
        /// This overload exists to disallow usage of Except with a left data source of type
        ///  and a right data source of type .
        /// Otherwise, the Except operator would appear to be binding to the parallel implementation, 
        /// but would in reality bind to the sequential implementation.
        ///  
        [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)] 
        public static ParallelQuery Except(
            this ParallelQuery first, IEnumerable second, IEqualityComparer comparer) 
        {
            throw new NotSupportedException(SR.GetString(SR.ParallelEnumerable_BinaryOpMustUseAsParallel));
        }
 
        /*====================================================================================
         * DATA TYPE CONVERSION OPERATORS 
         *===================================================================================*/ 

        //----------------------------------------------------------------------------------- 
        // For compatability with LINQ. Changes the static type to be less specific if needed.
        //

        ///  
        /// Converts a  into an
        ///  to force sequential 
        /// evaluation of the query. 
        /// 
        /// The type of the elements of . 
        /// The sequence to type as .
        /// The input sequence types as .
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static IEnumerable AsEnumerable(this ParallelQuery source) 
        { 
            return AsSequential(source);
        } 

       //------------------------------------------------------------------------------------
        // Simply generates a single-dimensional array containing the elements from the
        // provided enumerable object. 
        //
 
        ///  
        /// Creates an array from a ParallelQuery{T}.
        ///  
        /// The type of the elements of .
        /// A sequence to create an array from.
        /// An array that contains the elements from the input sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled.
        /// 
        public static TSource[] ToArray(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
 
            QueryOperator asOperator = source as QueryOperator;
 
            if (asOperator != null)
            {
                return asOperator.ExecuteAndGetResultsAsArray();
            } 

            return ToList(source).ToArray(); 
        } 

        //------------------------------------------------------------------------------------ 
        // The ToList method is similar to the ToArray methods above, except that they return
        // List objects. An overload is provided to specify the length, if desired.
        //
 
        /// 
        /// Creates a List{T} from an ParallelQuery{T}. 
        ///  
        /// The type of the elements of .
        /// A sequence to create a List<(Of <(T>)>) from. 
        /// A List<(Of <(T>)>) that contains elements from the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static List ToList(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // Allocate a growable list (optionally passing the length as the initial size). 
            List list = new List(); 
            IEnumerator input;
            QueryOperator asOperator = source as QueryOperator; 

            if (asOperator != null)
            {
                if (asOperator.OrdinalIndexState == OrdinalIndexState.Indexible && asOperator.OutputOrdered) 
                {
                    // If the query is indexible and the output is ordered, we will use the array-based merge. 
                    // That way, we avoid the ordering overhead. Due to limitations of the List<> class, the 
                    // most efficient solution seems to be to first dump all results into the array, and then
                    // copy them over into a List<>. 
                    //
                    // The issue is that we cannot efficiently construct a List<> with a fixed size. We can
                    // construct a List<> with a fixed *capacity*, but we still need to call Add() N times
                    // in order to be able to index into the List<>. 
                    return new List(ToArray(source));
                } 
 
                // We will enumerate the list w/out pipelining.
 
                // @PERF: there are likely some cases, e.g. for very large data sets,
                //     where we want to use pipelining for this operation. It can reduce memory
                //     usage since, as we enumerate w/ pipelining off, we're already accumulating
                //     results into a buffer. As a matter of fact, there's probably a way we can 
                //     just directly use that buffer below instead of creating a new list.
 
                input = asOperator.GetEnumerator(ParallelMergeOptions.FullyBuffered); 
            }
            else 
            {
                input = source.GetEnumerator();
            }
 
            // Now, accumulate the results into a dynamically sized list, stopping if we reach
            // the (optionally specified) maximum length. 
            Contract.Assert(input != null); 
            using (input)
            { 
                while (input.MoveNext())
                {
                    list.Add(input.Current);
                } 
            }
 
            return list; 
        }
 
        //-----------------------------------------------------------------------------------
        // ToDictionary constructs a dictionary from an instance of ParallelQuery.
        // Each element in the enumerable is converted to a (key,value) pair using a pair
        // of lambda expressions specified by the caller. Different elements must produce 
        // different keys or else ArgumentException is thrown.
        // 
 
        /// 
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to 
        /// a specified key selector function.
        /// 
        /// The type of the elements of .
        /// The type of the key returned by . 
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from.
        /// A function to extract a key from each element. 
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains keys and values. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements.
        /// -or- 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector) 
        {
            return ToDictionary(source, keySelector, EqualityComparer.Default); 
        } 

        ///  
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to a
        /// specified key selector function and key comparer.
        /// 
        /// The type of the elements of . 
        /// The type of the key returned by .
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from. 
        /// A function to extract a key from each element. 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains keys and values. 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements. 
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
            Dictionary result = new Dictionary(comparer);
 
            QueryOperator op = source as QueryOperator;
            IEnumerator input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true); 
 
            using(input)
            { 
                while (input.MoveNext())
                {
                    TKey key;
                    TSource val = input.Current; 
                    try
                    { 
                        key = keySelector(val); 
                    	result.Add(key, val);
                    } 
                    catch (ThreadAbortException)
                    {
                        // Do not wrap ThreadAbortExceptions
                        throw; 
                    }
                    catch (Exception ex) 
                    { 
                        throw new AggregateException(ex);
                    } 
                }
            }

            return result; 
        }
 
        ///  
        /// Creates a Dictionary{TKey,TValue} from a ParallelQuery{T} according to specified
        /// key selector and element selector functions. 
        /// 
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the value returned by . 
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from.
        /// A function to extract a key from each element. 
        ///  
        /// A transform function to produce a result element value from each element.
        ///  
        /// 
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains values of type 
        /// selected from the input sequence
        ///  
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        ///  produces a key that is a null reference (Nothing in Visual Basic). 
        /// -or-
        ///  produces duplicate keys for two elements.
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static Dictionary ToDictionary( 
            this ParallelQuery source, Func keySelector, Func elementSelector)
        {
            return ToDictionary(source, keySelector, elementSelector, EqualityComparer.Default);
        } 

        ///  
        /// Creates a Dictionary{TKey,TValue from a ParallelQuery{T} according to a 
        /// specified key selector function, a comparer, and an element selector function.
        ///  
        /// The type of the elements of .
        /// The type of the key returned by .
        /// The type of the value returned by .
        /// A sequence to create a Dictionary<(Of <(TKey, TValue>)>) from. 
        /// A function to extract a key from each element.
        /// A transform function to produce a result element 
        /// value from each element. 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        ///  
        /// A Dictionary<(Of <(TKey, TValue>)>) that contains values of type 
        /// selected from the input sequence
        /// 
        ///  
        ///  or  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        ///  produces a key that is a null reference (Nothing in Visual Basic).
        /// -or- 
        ///  produces duplicate keys for two elements.
        /// -or-
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static Dictionary ToDictionary(
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            // comparer may be null. In that case, the Dictionary constructor will use the default comparer. 
            Dictionary result = new Dictionary(comparer); 

            QueryOperator op = source as QueryOperator; 
            IEnumerator input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);

            using(input)
            { 
                while (input.MoveNext())
                { 
                    TSource src = input.Current; 

                    try 
                    {
                        result.Add(keySelector(src), elementSelector(src));
                    }
                    catch (ThreadAbortException) 
                    {
                        // Do not wrap ThreadAbortExceptions 
                        throw; 
                    }
                    catch(Exception ex) 
                    {
                        throw new AggregateException(ex);
                    }
                } 
            }
 
            return result; 
        }
 
        //------------------------------------------------------------------------------------
        // ToLookup constructs a lookup from an instance of ParallelQuery.
        // Each element in the enumerable is converted to a (key,value) pair using a pair
        // of lambda expressions specified by the caller. Multiple elements are allowed 
        // to produce the same key.
        // 
 
        /// 
        /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified key selector function. 
        /// 
        /// The type of elements of .
        /// The type of the key returned by .
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from. 
        /// A function to extract a key from each element.
        /// A Lookup<(Of <(TKey, TElement>)>) that contains keys and values. 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static ILookup ToLookup( 
            this ParallelQuery source, Func keySelector)
        { 
            return ToLookup(source, keySelector, EqualityComparer.Default);
        }

        ///  
        /// Creates an ILookup{TKey,T} from a ParallelQuery{T} according to a specified
        /// key selector function and key comparer. 
        ///  
        /// The type of elements of .
        /// The type of the key returned by . 
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from.
        /// A function to extract a key from each element.
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        /// A Lookup<(Of <(TKey, TElement>)>) that contains keys and values. 
        /// 
        ///  or  or is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, IEqualityComparer comparer) 
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector"); 

            // comparer may be null. In that case, GroupBy will use the default comparer.
            ParallelQuery> groupings = source.GroupBy(keySelector, comparer);
 
            Parallel.Lookup lookup = new Parallel.Lookup(comparer);
 
            Contract.Assert(groupings is QueryOperator>); 
            QueryOperator> op = groupings as QueryOperator>;
 
            IEnumerator> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);

            using(input)
            { 
                while (input.MoveNext())
                { 
                    lookup.Add(input.Current); 
                }
            } 

            return lookup;
        }
 
        /// 
        /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to specified 
        /// key selector and element selector functions. 
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// The type of the value returned by .
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from.
        /// A function to extract a key from each element. 
        /// 
        /// A transform function to produce a result element value from each element. 
        ///  
        /// 
        /// A Lookup<(Of <(TKey, TElement>)>) that contains values of type TElement 
        /// selected from the input sequence.
        /// 
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, Func elementSelector) 
        {
            return ToLookup(source, keySelector, elementSelector, EqualityComparer.Default); 
        } 

        ///  
        /// Creates an ILookup{TKey,TElement} from a ParallelQuery{T} according to
        /// a specified key selector function, a comparer and an element selector function.
        /// 
        /// The type of elements of . 
        /// The type of the key returned by .
        /// The type of the value returned by . 
        /// The sequence to create a Lookup<(Of <(TKey, TElement>)>) from. 
        /// A function to extract a key from each element.
        ///  
        /// A transform function to produce a result element value from each element.
        /// 
        /// An IEqualityComparer<(Of <(T>)>) to compare keys.
        ///  
        /// A Lookup<(Of <(TKey, TElement>)>) that contains values of type TElement selected
        /// from the input sequence. 
        ///  
        /// 
        ///  or  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static ILookup ToLookup(
            this ParallelQuery source, Func keySelector, Func elementSelector, IEqualityComparer comparer) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");
            if (elementSelector == null) throw new ArgumentNullException("elementSelector"); 

            // comparer may be null. In that case, GroupBy will use the default comparer. 
            ParallelQuery> groupings = source.GroupBy(keySelector, elementSelector, comparer); 

            Parallel.Lookup lookup = new Parallel.Lookup(comparer); 

            Contract.Assert(groupings is QueryOperator>);
            QueryOperator> op = groupings as QueryOperator>;
 
            IEnumerator> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
 
            using(input) 
            {
                while (input.MoveNext()) 
                {
                    lookup.Add(input.Current);
                }
            } 

            return lookup; 
        } 

        /*=================================================================================== 
         * MISCELLANEOUS OPERATORS
         *===================================================================================*/

        //----------------------------------------------------------------------------------- 
        // Reverses the input.
        // 
 
        /// 
        /// Inverts the order of the elements in a parallel sequence. 
        /// 
        /// The type of the elements of .
        /// A sequence of values to reverse.
        /// A sequence whose elements correspond to those of the input sequence in reverse order. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery Reverse(this ParallelQuery source)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new ReverseQueryOperator(source);
        }
 
        //-----------------------------------------------------------------------------------
        // Both OfType and Cast convert a weakly typed stream to a strongly typed one: 
        // the difference is that OfType filters out elements that aren't of the given type, 
        // while Cast forces the cast, possibly resulting in InvalidCastExceptions.
        // 

        /// 
        /// Filters the elements of a ParallelQuery based on a specified type.
        ///  
        /// The type to filter the elements of the sequence on.
        /// The sequence whose elements to filter. 
        /// A sequence that contains elements from the input sequence of type . 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery OfType(this ParallelQuery source)
        {
            if (source == null) throw new ArgumentNullException("source"); 

            return source.OfType(); 
        } 

        ///  
        /// Converts the elements of a ParallelQuery to the specified type.
        /// 
        /// The type to convert the elements of  to.
        /// The sequence that contains the elements to be converted. 
        /// 
        /// A sequence that contains each element of the source sequence converted to the specified type. 
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        public static ParallelQuery Cast(this ParallelQuery source)
        {
            return source.Cast(); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Helper method used by First, FirstOrDefault, Last, LastOrDefault, Single, and
        // SingleOrDefault below.  This takes a query operator, gets the first item (and 
        // either checks or asserts there is at most one item in the source), and returns it.
        // If there are no elements, the method either throws an exception or, if
        // defaultIfEmpty is true, returns a default value.
        // 
        // Arguments:
        //     queryOp        - the query operator to enumerate (for the single element) 
        //     throwIfTwo     - whether to throw an exception (true) or assert (false) that 
        //                      there is no more than one element in the source
        //     defaultIfEmpty - whether to return a default value (true) or throw an 
        //                      exception if the output of the query operator is empty
        //

        private static TSource GetOneWithPossibleDefault( 
            QueryOperator queryOp, bool throwIfTwo, bool defaultIfEmpty)
        { 
            Contract.Assert(queryOp != null, "expected query operator"); 

            using (IEnumerator e = queryOp.GetEnumerator(ParallelMergeOptions.FullyBuffered)) 
            {
                if (e.MoveNext())
                {
                    TSource current = e.Current; 

                    // Some operators need to do a runtime, retail check for more than one element. 
                    // Others can simply ----sert that there was only one. 
                    if (throwIfTwo)
                    { 
                        if (e.MoveNext())
                        {
                            throw new InvalidOperationException(SR.GetString(SR.MoreThanOneMatch));
                        } 
                    }
                    else 
                    { 
                        Contract.Assert(!e.MoveNext(), "expected only a single element");
                    } 

                    return current;
                }
            } 

            if (defaultIfEmpty) 
            { 
                return default(TSource);
            } 
            else
            {
                throw new InvalidOperationException(SR.GetString(SR.NoElements));
            } 
        }
 
        //----------------------------------------------------------------------------------- 
        // First simply returns the first element from the data source; if the predicate
        // overload is used, the first element satisfying the predicate is returned. 
        // An exception is thrown for empty data sources. Alternatively, the FirstOrDefault
        // method can be used which returns defualt(T) if empty (or no elements satisfy the
        // predicate).
        // 

        ///  
        /// Returns the first element of a parallel sequence. 
        /// The type of the elements of .
        /// The sequence to return the first element of. 
        /// The first element in the specified sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        ///  contains no elements. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource First(this ParallelQuery source)
        { 
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the 0th element.
            if (source == null) throw new ArgumentNullException("source"); 

            FirstQueryOperator queryOp = new FirstQueryOperator(source, null);

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
                    .First();
            } 

            return GetOneWithPossibleDefault(queryOp, false, false); 
        } 

        ///  
        /// Returns the first element in a parallel sequence that satisfies a specified condition.
        /// 
        /// There's a temporary difference from LINQ to Objects, this does not throw
        /// ArgumentNullException when the predicate is null. 
        /// The type of the elements of .
        /// The sequence to return an element from. 
        /// A function to test each element for a condition. 
        /// The first element in the sequence that passes the test in the specified predicate function.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        /// No element in  satisfies the condition in . 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static TSource First(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 
 
            FirstQueryOperator queryOp = new FirstQueryOperator(source, predicate);
 
            // If in conservative mode and a premature merge would be inserted by the First operator,
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState)
                    .First(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState)); 
            }

            return GetOneWithPossibleDefault(queryOp, false, false);
 
        }
 
        ///  
        /// Returns the first element of a parallel sequence, or a default value if the
        /// sequence contains no elements. 
        /// 
        /// The type of the elements of .
        /// The sequence to return the first element of.
        ///  
        /// default(TSource) if  is empty; otherwise, the first element in .
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource FirstOrDefault(this ParallelQuery source) 
        {
            if (source == null) throw new ArgumentNullException("source"); 

            // @PERF: optimize for seekable data sources.  E.g. if an array, we can
            //     seek directly to the 0th element.
            FirstQueryOperator queryOp = new FirstQueryOperator(source, null); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially. 
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks,
                    settings.CancellationState).FirstOrDefault(); 
            } 

            return GetOneWithPossibleDefault(queryOp, false, true); 
        }

        /// 
        /// Returns the first element of the parallel sequence that satisfies a condition or a 
        /// default value if no such element is found.
        ///  
        /// There's a temporary difference from LINQ to Objects, this does not throw 
        /// ArgumentNullException when the predicate is null.
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition.
        /// 
        /// default(TSource) if  is empty or if no element passes the test 
        /// specified by predicate; otherwise, the first element in  that
        /// passes the test specified by predicate. 
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        /// 
        /// The query was canceled. 
        ///  
        public static TSource FirstOrDefault(this ParallelQuery source, Func predicate)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");

            FirstQueryOperator queryOp = new FirstQueryOperator(source, predicate); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially. 
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(
                    childWithCancelChecks, settings.CancellationState) 
                    .FirstOrDefault(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState)); 
            }
 
            return GetOneWithPossibleDefault(queryOp, false, true);
        }

        //------------------------------------------------------------------------------------ 
        // Last simply returns the last element from the data source; if the predicate
        // overload is used, the last element satisfying the predicate is returned. 
        // An exception is thrown for empty data sources. Alternatively, the LastOrDefault 
        // method can be used which returns defualt(T) if empty (or no elements satisfy the
        // predicate). 
        //

        /// 
        /// Returns the last element of a parallel sequence. 
        /// The type of the elements of .
        /// The sequence to return the last element from. 
        /// The value at the last position in the source sequence. 
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        /// 
        ///  contains no elements.
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TSource Last(this ParallelQuery source)
        {
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the last element.
            if (source == null) throw new ArgumentNullException("source"); 
 
            LastQueryOperator queryOp = new LastQueryOperator(source, null);
 
            // If in conservative mode and a premature merge would be inserted by the First operator,
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            { 
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).Last(); 
            }

            return GetOneWithPossibleDefault(queryOp, false, false);
        } 

        ///  
        /// Returns the last element of a parallel sequence that satisfies a specified condition. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition.
        /// 
        /// The last element in the sequence that passes the test in the specified predicate function. 
        /// 
        ///  
        ///  or  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// No element in  satisfies the condition in .
        /// 
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled. 
        /// 
        public static TSource Last(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            LastQueryOperator queryOp = new LastQueryOperator(source, predicate);
 
            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable( 
                    childWithCancelChecks, settings.CancellationState) 
                    .Last(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState));
            } 

            return GetOneWithPossibleDefault(queryOp, false, false);
        }
 
        /// 
        /// Returns the last element of a parallel sequence, or a default value if the 
        /// sequence contains no elements. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// 
        /// default() if the source sequence is empty; otherwise, the last element in the sequence.
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource LastOrDefault(this ParallelQuery source)
        { 
            // @PERF: optimize for seekable data sources.  E.g. if an array, we can 
            //     seek directly to the last element.
            if (source == null) throw new ArgumentNullException("source"); 

            LastQueryOperator queryOp = new LastQueryOperator(source, null);

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults(); 
            if (queryOp.LimitsParallelism 
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism)
            { 
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken);
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken);
                return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).LastOrDefault();
            } 

            return GetOneWithPossibleDefault(queryOp, false, true); 
        } 

        ///  
        /// Returns the last element of a parallel sequence that satisfies a condition, or
        /// a default value if no such element is found.
        /// 
        /// The type of the elements of . 
        /// The sequence to return an element from.
        /// A function to test each element for a condition. 
        ///  
        /// default() if the sequence is empty or if no elements pass the test in the
        /// predicate function; otherwise, the last element that passes the test in the predicate function. 
        /// 
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        ///  
        /// 
        /// The query was canceled. 
        /// 
        public static TSource LastOrDefault(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");
 
            LastQueryOperator queryOp = new LastQueryOperator(source, predicate); 

            // If in conservative mode and a premature merge would be inserted by the First operator, 
            // run the whole query sequentially.
            QuerySettings settings = queryOp.SpecifiedQuerySettings.WithDefaults();
            if (queryOp.LimitsParallelism
                && settings.ExecutionMode != ParallelExecutionMode.ForceParallelism) 
            {
                IEnumerable childAsSequential = queryOp.Child.AsSequentialQuery(settings.CancellationState.ExternalCancellationToken); 
                IEnumerable childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, settings.CancellationState.ExternalCancellationToken); 
                return ExceptionAggregator.WrapEnumerable(
                    childWithCancelChecks, settings.CancellationState) 
                    .LastOrDefault(ExceptionAggregator.WrapFunc(predicate, settings.CancellationState));
            }

            return GetOneWithPossibleDefault(queryOp, false, true); 
        }
 
        //------------------------------------------------------------------------------------ 
        // Single yields the single element matching the optional predicate, or throws an
        // exception if there is zero or more than one match. SingleOrDefault is similar 
        // except that it returns the default value in this condition.
        //

        ///  
        /// Returns the only element of a parallel sequence, and throws an exception if there is not
        /// exactly one element in the sequence. 
        ///  
        /// The type of the elements of .
        /// The sequence to return the single element of. 
        /// The single element of the input sequence.
        /// 
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// The input sequence contains more than one element. -or- The input sequence is empty. 
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        /// 
        /// The query was canceled.
        ///  
        public static TSource Single(this ParallelQuery source)
        { 
            // @PERF: optimize for ICollection-typed data sources, i.e. we can just 
            //     check the Count property and avoid costly fork/join/synchronization.
            if (source == null) throw new ArgumentNullException("source"); 

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, null), true, false);
        }
 
        /// 
        /// Returns the only element of a parallel sequence that satisfies a specified condition, 
        /// and throws an exception if more than one such element exists. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return the single element of.
        /// A function to test an element for a condition.
        /// The single element of the input sequence that satisfies a condition.
        ///  
        ///  or  is a null reference (Nothing in Visual Basic).
        ///  
        ///  
        /// No element satisfies the condition in . -or- More than one element satisfies the condition in .
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource Single(this ParallelQuery source, Func predicate) 
        {
            if (source == null) throw new ArgumentNullException("source"); 
            if (predicate == null) throw new ArgumentNullException("predicate");

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, predicate), true, false);
        } 

        ///  
        /// Returns the only element of a parallel sequence, or a default value if the sequence is 
        /// empty; this method throws an exception if there is more than one element in the sequence.
        ///  
        /// The type of the elements of .
        /// The sequence to return the single element of.
        /// 
        /// The single element of the input sequence, or default() if the 
        /// sequence contains no elements.
        ///  
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        ///  
        /// 
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        ///  
        /// The query was canceled.
        ///  
        public static TSource SingleOrDefault(this ParallelQuery source) 
        {
            // @PERF: optimize for ICollection-typed data sources, i.e. we can just 
            //     check the Count property and avoid costly fork/join/synchronization.
            if (source == null) throw new ArgumentNullException("source");

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, null), true, true); 
        }
 
        ///  
        /// Returns the only element of a parallel sequence that satisfies a specified condition
        /// or a default value if no such element exists; this method throws an exception 
        /// if more than one element satisfies the condition.
        /// 
        /// The type of the elements of .
        /// The sequence to return the single element of. 
        /// A function to test an element for a condition.
        ///  
        /// The single element of the input sequence that satisfies the condition, or 
        /// default() if no such element is found.
        ///  
        /// 
        ///  or  is a null reference (Nothing in Visual Basic).
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        ///  
        ///  
        /// The query was canceled.
        ///  
        public static TSource SingleOrDefault(this ParallelQuery source, Func predicate)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (predicate == null) throw new ArgumentNullException("predicate"); 

            return GetOneWithPossibleDefault(new SingleQueryOperator(source, predicate), true, true); 
        } 

        //----------------------------------------------------------------------------------- 
        // DefaultIfEmpty yields the data source, unmodified, if it is non-empty. Otherwise,
        // it yields a single occurrence of the default value.
        //
 
        /// 
        /// Returns the elements of the specified parallel sequence or the type parameter's 
        /// default value in a singleton collection if the sequence is empty. 
        /// 
        /// The type of the elements of . 
        /// The sequence to return a default value for if it is empty.
        /// 
        /// A sequence that contains default(TSource) if  is empty; otherwise, .
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery DefaultIfEmpty(this ParallelQuery source)
        { 
            return DefaultIfEmpty(source, default(TSource));
        }

        ///  
        /// Returns the elements of the specified parallel sequence or the specified value
        /// in a singleton collection if the sequence is empty. 
        ///  
        /// The type of the elements of .
        /// The sequence to return the specified value for if it is empty. 
        /// The value to return if the sequence is empty.
        /// 
        /// A sequence that contains defaultValue if  is empty; otherwise, .
        ///  
        /// 
        ///  is a null reference (Nothing in Visual Basic). 
        ///  
        public static ParallelQuery DefaultIfEmpty(this ParallelQuery source, TSource defaultValue)
        { 
            if (source == null) throw new ArgumentNullException("source");
            return new DefaultIfEmptyQueryOperator(source, defaultValue);
        }
 
        //------------------------------------------------------------------------------------
        // ElementAt yields an element at a specific index.  If the data source doesn't 
        // contain such an element, an exception is thrown.  Alternatively, ElementAtOrDefault 
        // will return a default value if the given index is invalid.
        // 

        /// 
        /// Returns the element at a specified index in a parallel sequence.
        ///  
        /// The type of the elements of .
        /// A sequence to return an element from. 
        /// The zero-based index of the element to retrieve. 
        /// The element at the specified position in the source sequence.
        ///  
        ///  is a null reference (Nothing in Visual Basic).
        /// 
        /// 
        ///  is less than 0 or greater than or equal to the number of elements in . 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query. 
        /// 
        ///  
        /// The query was canceled.
        /// 
        public static TSource ElementAt(this ParallelQuery source, int index)
        { 
            if (source == null) throw new ArgumentNullException("source");
            if (index < 0) throw new ArgumentOutOfRangeException("index"); 
 
            // @PERF: there are obvious optimization opportunities for indexible data sources,
            //          since we can just seek to the element requested. 

            ElementAtQueryOperator op = new ElementAtQueryOperator(source, index);

            TSource result; 
            if (op.Aggregate(out result, false))
            { 
                return result; 
            }
 
            throw new ArgumentOutOfRangeException("index");
        }

        ///  
        /// Returns the element at a specified index in a parallel sequence or a default value if the
        /// index is out of range. 
        ///  
        /// The type of the elements of .
        /// A sequence to return an element from. 
        /// The zero-based index of the element to retrieve.
        /// 
        /// default(TSource) if the index is outside the bounds of the source sequence;
        /// otherwise, the element at the specified position in the source sequence. 
        /// 
        ///  
        ///  is a null reference (Nothing in Visual Basic). 
        /// 
        ///  
        /// One or more exceptions occurred during the evaluation of the query.
        /// 
        /// 
        /// The query was canceled. 
        /// 
        public static TSource ElementAtOrDefault(this ParallelQuery source, int index) 
        { 
            if (source == null) throw new ArgumentNullException("source");
 
            // @PERF: there are obvious optimization opportunities for indexible data sources,
            //          since we can just seek to the element requested.

            if (index >= 0) 
            {
                ElementAtQueryOperator op = new ElementAtQueryOperator(source, index); 
 
                TSource result;
                if (op.Aggregate(out result, true)) 
                {
                    return result;
                }
            } 

            return default(TSource); 
        } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK