Annotate System.Linq.Parallel for nullable ref types (dotnet/corefx#41533)
authorbuyaa-n <bunamnan@microsoft.com>
Fri, 25 Oct 2019 16:35:56 +0000 (09:35 -0700)
committerGitHub <noreply@github.com>
Fri, 25 Oct 2019 16:35:56 +0000 (09:35 -0700)
* Nullable annotation for System.Linq.Parallel

Commit migrated from https://github.com/dotnet/corefx/commit/4a863a6232477c673f7a41aae656f5054f9dbc78

117 files changed:
src/libraries/System.Linq.Parallel/ref/System.Linq.Parallel.cs
src/libraries/System.Linq.Parallel/ref/System.Linq.Parallel.csproj
src/libraries/System.Linq.Parallel/src/System.Linq.Parallel.csproj
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Channels/AsynchronousChannel.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Channels/SynchronousChannel.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/AggregationMinMaxHelpers.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EmptyEnumerable.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/EnumerableWrapperWeakToStrong.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/ParallelEnumerableWrapper.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/ParallelQuery.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/RangeEnumerable.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Enumerables/RepeatEnumerable.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Helpers.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/AsynchronousChannelMergeEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/DefaultMergeHelper.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/IMergeHelper.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/MergeEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/MergeExecutor.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/OrderPreservingMergeHelper.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/OrderPreservingPipeliningMergeHelper.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Merging/SynchronousChannelMergeEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/HashRepartitionEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/HashRepartitionStream.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/OrderedHashRepartitionEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/OrderedHashRepartitionStream.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/PartitionedDataSource.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Partitioning/UnorderedHashRepartitionStream.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/AssociativeAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/ConcatQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/ExceptQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/GroupJoinQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/HashJoinQueryOperatorEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/IntersectQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/JoinQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/UnionQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Binary/ZipQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/BinaryQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/CountAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DecimalAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DecimalMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DecimalSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DoubleAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DoubleMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/DoubleSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/FloatAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/FloatMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/FloatSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/InlinedAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/InlinedAggregationOperatorEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/IntAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/IntMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/IntSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/LongAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/LongCountAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/LongMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/LongSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDecimalAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDecimalMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDecimalSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDoubleAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDoubleMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableDoubleSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableFloatAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableFloatMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableFloatSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableIntAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableIntMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableIntSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableLongAverageAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableLongMinMaxAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Inlined/NullableLongSumAggregationOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Options/OrderingQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/PartitionedStreamMerger.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/PartitionerQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/QueryOpeningEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/QueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/QueryOperatorEnumerator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/QuerySettings.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/ScanQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/AnyAllSearchOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/ContainsSearchOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/DefaultIfEmptyQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/DistinctQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/ElementAtQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/FirstQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/ForAllOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/GroupByQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/IndexedSelectQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/IndexedWhereQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/LastQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/ReverseQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/SelectManyQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/SelectQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/SingleQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/SortQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/TakeOrSkipQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/TakeOrSkipWhileQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/Unary/WhereQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/QueryOperators/UnaryQueryOperator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/CancellationState.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/OrderPreservingPipeliningSpoolingTask.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/OrderPreservingSpoolingTask.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/QueryTask.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/QueryTaskGroupState.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/Scheduling.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/SpoolingTask.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Scheduling/SpoolingTaskBase.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/ExceptionAggregator.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/ExchangeUtilities.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/HashLookup.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/ListChunk.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/Lookup.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/Pair.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/PairComparer.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/Sorting.cs
src/libraries/System.Linq.Parallel/src/System/Linq/Parallel/Utils/WrapperEqualityComparer.cs
src/libraries/System.Linq.Parallel/src/System/Linq/ParallelEnumerable.cs

index ebf2e374f6be193f4284ac67a6f14c04bd4efa27..d3b841695c8c358ce0ebd93b8a21b8c7359659d1 100644 (file)
@@ -55,54 +55,59 @@ namespace System.Linq
         public static System.Linq.ParallelQuery<TSource> Concat<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Concat<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second) { throw null; }
         public static bool Contains<TSource>(this System.Linq.ParallelQuery<TSource> source, TSource value) { throw null; }
-        public static bool Contains<TSource>(this System.Linq.ParallelQuery<TSource> source, TSource value, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static bool Contains<TSource>(this System.Linq.ParallelQuery<TSource> source, TSource value, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static int Count<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static int Count<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static System.Linq.ParallelQuery<TSource> DefaultIfEmpty<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static System.Linq.ParallelQuery<TSource> DefaultIfEmpty<TSource>(this System.Linq.ParallelQuery<TSource> source, TSource defaultValue) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Distinct<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
-        public static System.Linq.ParallelQuery<TSource> Distinct<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Distinct<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource ElementAtOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source, int index) { throw null; }
         public static TSource ElementAt<TSource>(this System.Linq.ParallelQuery<TSource> source, int index) { throw null; }
         public static System.Linq.ParallelQuery<TResult> Empty<TResult>() { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second) { throw null; }
-        public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Except<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource FirstOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource FirstOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static TSource First<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static TSource First<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static void ForAll<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Action<TSource> action) { }
         public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) { throw null; }
-        public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<System.Linq.IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TSource>, TResult> resultSelector) { throw null; }
-        public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TSource>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TSource>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TElement>, TResult> resultSelector) { throw null; }
-        public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TElement>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Func<TKey, System.Collections.Generic.IEnumerable<TElement>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector) { throw null; }
-        public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, System.Collections.Generic.IEnumerable<TInner>, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second) { throw null; }
-        public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Intersect<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Collections.Generic.IEnumerable<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector) { throw null; }
-        public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(this System.Linq.ParallelQuery<TOuter> outer, System.Linq.ParallelQuery<TInner> inner, System.Func<TOuter, TKey> outerKeySelector, System.Func<TInner, TKey> innerKeySelector, System.Func<TOuter, TInner, TResult> resultSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource LastOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource LastOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static TSource Last<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static TSource Last<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
@@ -118,6 +123,7 @@ namespace System.Linq
         public static long? Max(this System.Linq.ParallelQuery<long?> source) { throw null; }
         public static float? Max(this System.Linq.ParallelQuery<float?> source) { throw null; }
         public static float Max(this System.Linq.ParallelQuery<float> source) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource Max<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static decimal Max<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, decimal> selector) { throw null; }
         public static double Max<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, double> selector) { throw null; }
@@ -129,6 +135,7 @@ namespace System.Linq
         public static long? Max<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, long?> selector) { throw null; }
         public static float? Max<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, float?> selector) { throw null; }
         public static float Max<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, float> selector) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TResult Max<TSource, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TResult> selector) { throw null; }
         public static decimal Min(this System.Linq.ParallelQuery<decimal> source) { throw null; }
         public static double Min(this System.Linq.ParallelQuery<double> source) { throw null; }
@@ -140,6 +147,7 @@ namespace System.Linq
         public static long? Min(this System.Linq.ParallelQuery<long?> source) { throw null; }
         public static float? Min(this System.Linq.ParallelQuery<float?> source) { throw null; }
         public static float Min(this System.Linq.ParallelQuery<float> source) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource Min<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static decimal Min<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, decimal> selector) { throw null; }
         public static double Min<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, double> selector) { throw null; }
@@ -151,12 +159,13 @@ namespace System.Linq
         public static long? Min<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, long?> selector) { throw null; }
         public static float? Min<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, float?> selector) { throw null; }
         public static float Min<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, float> selector) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TResult Min<TSource, TResult>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TResult> selector) { throw null; }
         public static System.Linq.ParallelQuery<TResult> OfType<TResult>(this System.Linq.ParallelQuery source) { throw null; }
         public static System.Linq.OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey> comparer) { throw null; }
+        public static System.Linq.OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer) { throw null; }
         public static System.Linq.OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey> comparer) { throw null; }
+        public static System.Linq.OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<int> Range(int start, int count) { throw null; }
         public static System.Linq.ParallelQuery<TResult> Repeat<TResult>(TResult element, int count) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Reverse<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
@@ -169,10 +178,12 @@ namespace System.Linq
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second) { throw null; }
-        public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static bool SequenceEqual<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource SingleOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
+        [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
         public static TSource SingleOrDefault<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static TSource Single<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
         public static TSource Single<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
@@ -203,25 +214,25 @@ namespace System.Linq
         public static System.Linq.ParallelQuery<TSource> TakeWhile<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, int, bool> predicate) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Take<TSource>(this System.Linq.ParallelQuery<TSource> source, int count) { throw null; }
         public static System.Linq.OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey> comparer) { throw null; }
+        public static System.Linq.OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer) { throw null; }
         public static System.Linq.OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey> comparer) { throw null; }
+        public static System.Linq.OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(this System.Linq.OrderedParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IComparer<TKey>? comparer) { throw null; }
         public static TSource[] ToArray<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
-        public static System.Collections.Generic.Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Collections.Generic.Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
-        public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) { throw null; }
-        public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Collections.Generic.Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) where TKey : notnull { throw null; }
+        public static System.Collections.Generic.Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) where TKey : notnull { throw null; }
+        public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) where TKey : notnull { throw null; }
+        public static System.Collections.Generic.Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) where TKey : notnull { throw null; }
         public static System.Collections.Generic.List<TSource> ToList<TSource>(this System.Linq.ParallelQuery<TSource> source) { throw null; }
-        public static System.Linq.ILookup<TKey, TSource> ToLookup<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) { throw null; }
-        public static System.Linq.ILookup<TKey, TSource> ToLookup<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
-        public static System.Linq.ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) { throw null; }
-        public static System.Linq.ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey> comparer) { throw null; }
+        public static System.Linq.ILookup<TKey, TSource> ToLookup<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector) where TKey : notnull { throw null; }
+        public static System.Linq.ILookup<TKey, TSource> ToLookup<TSource, TKey>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) where TKey : notnull { throw null; }
+        public static System.Linq.ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector) where TKey : notnull { throw null; }
+        public static System.Linq.ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, TKey> keySelector, System.Func<TSource, TElement> elementSelector, System.Collections.Generic.IEqualityComparer<TKey>? comparer) where TKey : notnull { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
         public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second) { throw null; }
         [System.ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
-        public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Collections.Generic.IEnumerable<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second) { throw null; }
-        public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource> comparer) { throw null; }
+        public static System.Linq.ParallelQuery<TSource> Union<TSource>(this System.Linq.ParallelQuery<TSource> first, System.Linq.ParallelQuery<TSource> second, System.Collections.Generic.IEqualityComparer<TSource>? comparer) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Where<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, bool> predicate) { throw null; }
         public static System.Linq.ParallelQuery<TSource> Where<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Func<TSource, int, bool> predicate) { throw null; }
         public static System.Linq.ParallelQuery<TSource> WithCancellation<TSource>(this System.Linq.ParallelQuery<TSource> source, System.Threading.CancellationToken cancellationToken) { throw null; }
index 639a0b04231ee532e830e6c2815f5c084b52d05f..8f3766799bdaf2ed7b4fd141dbe956f047ecc233 100644 (file)
@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <Configurations>netcoreapp-Debug;netcoreapp-Release</Configurations>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="System.Linq.Parallel.cs" />
index 64e1f038f7b8cb0a43b738ae2f95f6f340837455..a87011f4bb97e63e07434c1877acd0fcd276c2ac 100644 (file)
@@ -3,6 +3,7 @@
     <AssemblyName>System.Linq.Parallel</AssemblyName>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <Configurations>netcoreapp-Debug;netcoreapp-Release</Configurations>
+       <Nullable>enable</Nullable>
   </PropertyGroup>
   <!-- Compiled Source Files -->
   <ItemGroup>
index 31d1bba3d6fb83564b2b7a41b3c4dde400a0a3fd..f31f515bd7d5b8195632d01e9653739bf987c9b8 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -64,24 +65,24 @@ namespace System.Linq.Parallel
         //   1 consumer thread to access this thing concurrently. It's been carefully designed
         //   to avoid locking, but only because of this restriction...
 
-        private readonly T[][] _buffer;              // The buffer of chunks.
+        private readonly T[]?[] _buffer;              // The buffer of chunks.
         private readonly int _index;            // Index of this channel
         private volatile int _producerBufferIndex;   // Producer's current index, i.e. where to put the next chunk.
         private volatile int _consumerBufferIndex;   // Consumer's current index, i.e. where to get the next chunk.
 
         private volatile bool _done;        // Set to true once the producer is done.
 
-        private T[] _producerChunk;         // The temporary chunk being generated by the producer.
+        private T[]? _producerChunk;         // The temporary chunk being generated by the producer.
         private int _producerChunkIndex;    // A producer's index into its temporary chunk.
-        private T[] _consumerChunk;         // The temporary chunk being enumerated by the consumer.
+        private T[]? _consumerChunk;         // The temporary chunk being enumerated by the consumer.
         private int _consumerChunkIndex;    // A consumer's index into its temporary chunk.
 
         private readonly int _chunkSize;             // The number of elements that comprise a chunk.
 
         // These events are used to signal a waiting producer when the consumer dequeues, and to signal a
         // waiting consumer when the producer enqueues.
-        private ManualResetEventSlim _producerEvent;
-        private IntValueEvent _consumerEvent;
+        private ManualResetEventSlim? _producerEvent;
+        private IntValueEvent? _consumerEvent;
 
         // These two-valued ints track whether a producer or consumer _might_ be waiting. They are marked
         // volatile because they are used in synchronization critical regions of code (see usage below).
@@ -103,12 +104,12 @@ namespace System.Linq.Parallel
         //     individual elements.
         //
 
-        internal AsynchronousChannel(int index, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent) :
+        internal AsynchronousChannel(int index, int chunkSize, CancellationToken cancellationToken, IntValueEvent? consumerEvent) :
             this(index, Scheduling.DEFAULT_BOUNDED_BUFFER_CAPACITY, chunkSize, cancellationToken, consumerEvent)
         {
         }
 
-        internal AsynchronousChannel(int index, int capacity, int chunkSize, CancellationToken cancellationToken, IntValueEvent consumerEvent)
+        internal AsynchronousChannel(int index, int capacity, int chunkSize, CancellationToken cancellationToken, IntValueEvent? consumerEvent)
         {
             if (chunkSize == 0) chunkSize = Scheduling.GetDefaultChunkSize<T>();
 
@@ -255,6 +256,8 @@ namespace System.Linq.Parallel
 
         internal void Enqueue(T item)
         {
+            Debug.Assert(_producerChunk != null);
+
             // Store the element into our current chunk.
             int producerChunkIndex = _producerChunkIndex;
             _producerChunk[producerChunkIndex] = item;
@@ -310,6 +313,7 @@ namespace System.Linq.Parallel
             if (_consumerIsWaiting == 1 && !IsChunkBufferEmpty)
             {
                 TraceHelpers.TraceInfo("AsynchronousChannel::EnqueueChunk - producer waking consumer");
+                Debug.Assert(_consumerEvent != null);
                 _consumerIsWaiting = 0;
                 _consumerEvent.Set(_index);
             }
@@ -321,6 +325,8 @@ namespace System.Linq.Parallel
 
         private void WaitUntilNonFull()
         {
+            Debug.Assert(_producerEvent != null);
+
             // We must loop; sometimes the producer event will have been set
             // prematurely due to the way waiting flags are managed.  By looping,
             // we will only return from this method when space is truly available.
@@ -395,7 +401,7 @@ namespace System.Linq.Parallel
         //     True if an item was found, false otherwise.
         //
 
-        internal bool TryDequeue(ref T item)
+        internal bool TryDequeue([MaybeNullWhen(false), AllowNull] ref T item)
         {
             // Ensure we have a chunk to work with.
             if (_consumerChunk == null)
@@ -435,7 +441,7 @@ namespace System.Linq.Parallel
         //     True if a chunk was found, false otherwise.
         //
 
-        private bool TryDequeueChunk(ref T[] chunk)
+        private bool TryDequeueChunk([NotNullWhen(true)] ref T[]? chunk)
         {
             // This is the non-blocking version of dequeue. We first check to see
             // if the queue is empty. If the caller chooses to wait later, they can
@@ -471,7 +477,7 @@ namespace System.Linq.Parallel
         //     eventually regardless of whether the caller actually waits or not.
         //
 
-        internal bool TryDequeue(ref T item, ref bool isDone)
+        internal bool TryDequeue([MaybeNullWhen(false), AllowNull] ref T item, ref bool isDone)
         {
             isDone = false;
 
@@ -524,7 +530,7 @@ namespace System.Linq.Parallel
         //     eventually regardless of whether the caller actually waits or not.
         //
 
-        private bool TryDequeueChunk(ref T[] chunk, ref bool isDone)
+        private bool TryDequeueChunk([NotNullWhen(true)] ref T[]? chunk, ref bool isDone)
         {
             isDone = false;
 
@@ -603,7 +609,7 @@ namespace System.Linq.Parallel
             // We can safely read from the consumer index because we know no producers
             // will write concurrently.
             int consumerBufferIndex = _consumerBufferIndex;
-            T[] chunk = _buffer[consumerBufferIndex];
+            T[] chunk = _buffer[consumerBufferIndex]!;
 
             // Zero out contents to avoid holding on to memory for longer than necessary. This
             // ensures the entire chunk is eligible for GC sooner. (More important for big chunks.)
@@ -622,6 +628,7 @@ namespace System.Linq.Parallel
             if (_producerIsWaiting == 1 && !IsFull)
             {
                 TraceHelpers.TraceInfo("BoundedSingleLockFreeChannel::DequeueChunk - consumer waking producer");
+                Debug.Assert(_producerEvent != null);
                 _producerIsWaiting = 0;
                 _producerEvent.Set();
             }
index 063a9c61617d3b9e3ab905b3db7bc6294440f1f8..13544dfe09263f9a868a30d65cd07e85b8153a95 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     internal sealed class SynchronousChannel<T>
     {
         // We currently use the BCL FIFO queue internally, although any would do.
-        private Queue<T> _queue;
+        private Queue<T>? _queue;
 
 #if DEBUG
         // In debug builds, we keep track of when the producer is done (for asserts).
@@ -113,7 +113,7 @@ namespace System.Linq.Parallel
 
         internal void CopyTo(T[] array, int arrayIndex)
         {
-            Debug.Assert(array != null);
+            Debug.Assert(_queue != null && array != null);
 #if DEBUG
             Debug.Assert(_done, "Can only copy from the channel after it's done being added to");
 #endif
index a340a99892b65840f6b4acb965deeffa6bb2948a..eb9e79662011381943f434d50ceb3b1da6af5a27 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Linq.Parallel;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq
 {
@@ -20,6 +21,7 @@ namespace System.Linq
         // Helper method to find the minimum or maximum element in the source.
         //
 
+        [return: MaybeNull]
         private static T Reduce(IEnumerable<T> source, int sign)
         {
             Debug.Assert(source != null);
@@ -30,8 +32,8 @@ namespace System.Linq
             Func<Pair<bool, T>, T> resultSelector = MakeResultSelectorFunction();
 
             AssociativeAggregationOperator<T, Pair<bool, T>, T> aggregation =
-                new AssociativeAggregationOperator<T, Pair<bool, T>, T>(source, new Pair<bool, T>(false, default(T)), null,
-                                                                        true, intermediateReduce, finalReduce, resultSelector, default(T) != null, QueryAggregationOptions.AssociativeCommutative);
+                new AssociativeAggregationOperator<T, Pair<bool, T>, T>(source, new Pair<bool, T>(false, default), null,
+                                                                        true, intermediateReduce, finalReduce, resultSelector, default(T)! != null, QueryAggregationOptions.AssociativeCommutative);
 
             return aggregation.Aggregate();
         }
@@ -40,6 +42,7 @@ namespace System.Linq
         // Helper method to find the minimum element in the source.
         //
 
+        [return: MaybeNull]
         internal static T ReduceMin(IEnumerable<T> source)
         {
             return Reduce(source, -1);
@@ -49,6 +52,7 @@ namespace System.Linq
         // Helper method to find the maximum element in the source.
         //
 
+        [return: MaybeNull]
         internal static T ReduceMax(IEnumerable<T> source)
         {
             return Reduce(source, 1);
@@ -71,7 +75,7 @@ namespace System.Linq
                            // the existing accumulated result is equal to the sign requested by the function factory,
                            // we will return a new pair that contains the current element as the best item.  We will
                            // ignore null elements (for reference and nullable types) in the input stream.
-                           if ((default(T) != null || element != null) &&
+                           if ((default(T)! != null || element != null) &&
                                (!accumulator.First || Util.Sign(comparer.Compare(element, accumulator.Second)) == sign))
                            {
                                return new Pair<bool, T>(true, element);
@@ -98,7 +102,7 @@ namespace System.Linq
                            if (element.First &&
                                (!accumulator.First || Util.Sign(comparer.Compare(element.Second, accumulator.Second)) == sign))
                            {
-                               Debug.Assert(default(T) != null || element.Second != null, "nulls unexpected in final reduce");
+                               Debug.Assert(default(T)! != null || element.Second != null, "nulls unexpected in final reduce");
                                return new Pair<bool, T>(true, element.Second);
                            }
 
@@ -115,7 +119,7 @@ namespace System.Linq
             // empty sequences.  Else, we will just return the element, which may be null for other types.
             return delegate (Pair<bool, T> accumulator)
                        {
-                           Debug.Assert(accumulator.First || default(T) == null,
+                           Debug.Assert(accumulator.First || default(T)! == null,
                                            "for non-null types we expect an exception to be thrown before getting here");
                            return accumulator.Second;
                        };
index 141288eee4017ca6b69e589ec0ca0d228665cbca..2b69371d8053ccb854fa220e79b9d5c0ae406573 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -27,8 +28,8 @@ namespace System.Linq.Parallel
         }
 
         // A singleton cached and shared among callers.
-        private static volatile EmptyEnumerable<T> s_instance;
-        private static volatile EmptyEnumerator<T> s_enumeratorInstance;
+        private static volatile EmptyEnumerable<T>? s_instance;
+        private static volatile EmptyEnumerator<T>? s_enumeratorInstance;
 
         internal static EmptyEnumerable<T> Instance
         {
@@ -58,14 +59,15 @@ namespace System.Linq.Parallel
 
     internal class EmptyEnumerator<T> : QueryOperatorEnumerator<T, int>, IEnumerator<T>
     {
-        internal override bool MoveNext(ref T currentElement, ref int currentKey)
+        internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
         {
             return false;
         }
 
         // IEnumerator<T> methods.
-        public T Current { get { return default(T); } }
-        object IEnumerator.Current { get { return null; } }
+        [MaybeNull]
+        public T Current { get { return default!; } }
+        object? IEnumerator.Current { get { return null; } }
         public bool MoveNext() { return false; }
         void Collections.IEnumerator.Reset() { }
     }
index 11d0b06d87a1768f6eb4237790c00151e66c0a6e..eb8799ca5655102e0b03ed96b640b728666795d6 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -19,7 +20,7 @@ namespace System.Linq.Parallel
     /// a weakly typed IEnumerable object, allowing it to be accessed as a strongly typed
     /// IEnumerable{object}.
     /// </summary>
-    internal class EnumerableWrapperWeakToStrong : IEnumerable<object>
+    internal class EnumerableWrapperWeakToStrong : IEnumerable<object?>
     {
         private readonly IEnumerable _wrappedEnumerable; // The wrapped enumerable object.
 
@@ -38,7 +39,7 @@ namespace System.Linq.Parallel
             return ((IEnumerable<object>)this).GetEnumerator();
         }
 
-        public IEnumerator<object> GetEnumerator()
+        public IEnumerator<object?> GetEnumerator()
         {
             return new WrapperEnumeratorWeakToStrong(_wrappedEnumerable.GetEnumerator());
         }
@@ -47,7 +48,7 @@ namespace System.Linq.Parallel
         // A wrapper over IEnumerator that provides IEnumerator<object> interface
         //
 
-        private class WrapperEnumeratorWeakToStrong : IEnumerator<object>
+        private class WrapperEnumeratorWeakToStrong : IEnumerator<object?>
         {
             private readonly IEnumerator _wrappedEnumerator; // The weakly typed enumerator we've wrapped.
 
@@ -66,20 +67,19 @@ namespace System.Linq.Parallel
             // forward to the corresponding weakly typed IEnumerator methods.
             //
 
-            object IEnumerator.Current
+            object? IEnumerator.Current
             {
                 get { return _wrappedEnumerator.Current; }
             }
 
-            object IEnumerator<object>.Current
+            object? IEnumerator<object?>.Current
             {
                 get { return _wrappedEnumerator.Current; }
             }
 
             void IDisposable.Dispose()
             {
-                IDisposable disposable = _wrappedEnumerator as IDisposable;
-                if (disposable != null)
+                if (_wrappedEnumerator is IDisposable disposable)
                 {
                     disposable.Dispose();
                 }
index 2d69d52c6755315189cf7a3eaea5751b24037cb7..195c1c06b8cc7fa25cc058852bf8ccd6fa7a24b3 100644 (file)
@@ -18,7 +18,7 @@ namespace System.Linq.Parallel
     /// A simple implementation of the ParallelQuery{object} interface which wraps an
     /// underlying IEnumerable, such that it can be used in parallel queries.
     /// </summary>
-    internal class ParallelEnumerableWrapper : ParallelQuery<object>
+    internal class ParallelEnumerableWrapper : ParallelQuery<object?>
     {
         private readonly IEnumerable _source; // The wrapped enumerable object.
 
@@ -38,7 +38,7 @@ namespace System.Linq.Parallel
             return _source.GetEnumerator();
         }
 
-        public override IEnumerator<object> GetEnumerator()
+        public override IEnumerator<object?> GetEnumerator()
         {
             return new EnumerableWrapperWeakToStrong(_source).GetEnumerator();
         }
index 22a887d86963cfe7d1e7236e3869ff68696b89ae..47ce42b6126f0e0e2645c869b56a7825205cd7ac 100644 (file)
@@ -102,7 +102,7 @@ namespace System.Linq
 
         internal sealed override ParallelQuery<TCastTo> Cast<TCastTo>()
         {
-            return ParallelEnumerable.Select<TSource, TCastTo>(this, elem => (TCastTo)(object)elem);
+            return ParallelEnumerable.Select<TSource, TCastTo>(this, elem => (TCastTo)(object)elem!);
         }
 
         internal sealed override ParallelQuery<TCastTo> OfType<TCastTo>()
@@ -111,7 +111,7 @@ namespace System.Linq
             //      solution (because it results in two operators) but is simple to implement.
             return this
                 .Where<TSource>(elem => elem is TCastTo)
-                .Select<TSource, TCastTo>(elem => (TCastTo)(object)elem);
+                .Select<TSource, TCastTo>(elem => (TCastTo)(object)elem!);
         }
 
         internal override IEnumerator GetEnumeratorUntyped()
index fbf5a7c3cd740fb4c5873a2c6d59b429d98135a9..e39bb88be72b923ada8f2b175e44879c06880a52 100644 (file)
@@ -77,7 +77,7 @@ namespace System.Linq.Parallel
             private readonly int _from; // The initial value.
             private readonly int _count; // How many values to yield.
             private readonly int _initialIndex; // The ordinal index of the first value in the range.
-            private Shared<int> _currentCount; // The 0-based index of the current value. [allocate in moveNext to avoid false-sharing]
+            private Shared<int>? _currentCount; // The 0-based index of the current value. [allocate in moveNext to avoid false-sharing]
 
             //-----------------------------------------------------------------------------------
             // Creates a new enumerator.
index 7217c92ac30e2a37dd559ed5ee27f63bcfdc03e2..c2da1f5dc8d731c255e8c5436acd79ed83fe4a06 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -82,7 +83,7 @@ namespace System.Linq.Parallel
             private readonly TResult _element; // The element to repeat.
             private readonly int _count; // The number of times to repeat it.
             private readonly int _indexOffset; // Our index offset.
-            private Shared<int> _currentIndex; // The number of times we have already repeated it. [allocate in moveNext to avoid false-sharing]
+            private Shared<int>? _currentIndex; // The number of times we have already repeated it. [allocate in moveNext to avoid false-sharing]
 
             //-----------------------------------------------------------------------------------
             // Creates a new enumerator.
@@ -99,7 +100,7 @@ namespace System.Linq.Parallel
             // Basic IEnumerator<T> methods. These produce the repeating sequence..
             //
 
-            internal override bool MoveNext(ref TResult currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TResult currentElement, ref int currentKey)
             {
                 if (_currentIndex == null)
                     _currentIndex = new Shared<int>(-1);
index a9e729af340901360414c3e70808f3262e84424d..89be7e896663f361ff74c711ec6b04d319c866dc 100644 (file)
@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -33,7 +34,7 @@ namespace System.Linq.Parallel
         private const int InitialSize = 7;
         private const int HashCodeMask = 0x7FFFFFFF;
 
-        public Set(IEqualityComparer<TElement> comparer)
+        public Set(IEqualityComparer<TElement>? comparer)
         {
             if (comparer == null) comparer = EqualityComparer<TElement>.Default;
             _comparer = comparer;
@@ -67,7 +68,7 @@ namespace System.Linq.Parallel
             int last = -1;
             for (int i = _buckets[bucket] - 1; i >= 0; last = i, i = _slots[i].next)
             {
-                if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value, value))
+                if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value!, value)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
                 {
                     if (last < 0)
                     {
@@ -78,7 +79,7 @@ namespace System.Linq.Parallel
                         _slots[last].next = _slots[i].next;
                     }
                     _slots[i].hashCode = -1;
-                    _slots[i].value = default(TElement);
+                    _slots[i].value = default;
                     _slots[i].next = -1;
                     return true;
                 }
@@ -91,7 +92,7 @@ namespace System.Linq.Parallel
             int hashCode = InternalGetHashCode(value);
             for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].next)
             {
-                if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value, value)) return true;
+                if (_slots[i].hashCode == hashCode && _comparer.Equals(_slots[i].value!, value)) return true; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
             }
             if (add)
             {
@@ -133,7 +134,7 @@ namespace System.Linq.Parallel
         {
             internal int hashCode;
             internal int next;
-            internal TElement value;
+            [MaybeNull, AllowNull] internal TElement value;
         }
     }
 }
index 00cee5a61328368602e9c84c60918a655bc9f1d0..ca0b0f60df556e49091850f3fd81e540dd341d82 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -29,17 +30,17 @@ namespace System.Linq.Parallel
     internal sealed class AsynchronousChannelMergeEnumerator<T> : MergeEnumerator<T>
     {
         private readonly AsynchronousChannel<T>[] _channels; // The channels being enumerated.
-        private IntValueEvent _consumerEvent; // The consumer event.
+        private IntValueEvent? _consumerEvent; // The consumer event.
         private readonly bool[] _done;       // Tracks which channels are done.
         private int _channelIndex;  // The next channel from which we'll dequeue.
-        private T _currentElement;  // The remembered element from the previous MoveNext.
+        [MaybeNull, AllowNull] private T _currentElement = default;  // The remembered element from the previous MoveNext. TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/37511
 
         //-----------------------------------------------------------------------------------
         // Allocates a new enumerator over a set of one-to-one channels.
         //
 
         internal AsynchronousChannelMergeEnumerator(
-            QueryTaskGroupState taskGroupState, AsynchronousChannel<T>[] channels, IntValueEvent consumerEvent)
+            QueryTaskGroupState taskGroupState, AsynchronousChannel<T>[] channels, IntValueEvent? consumerEvent)
             : base(taskGroupState)
         {
             Debug.Assert(channels != null);
@@ -70,7 +71,7 @@ namespace System.Linq.Parallel
                     throw new InvalidOperationException(SR.PLINQ_CommonEnumerator_Current_NotStarted);
                 }
 
-                return _currentElement;
+                return _currentElement!;
             }
         }
 
@@ -98,7 +99,7 @@ namespace System.Linq.Parallel
             }
 
             // Else try the fast path.
-            if (!_done[index] && _channels[index].TryDequeue(ref _currentElement))
+            if (!_done[index] && _channels[index].TryDequeue(ref _currentElement!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
             {
                 _channelIndex = (index + 1) % _channels.Length;
                 return true;
@@ -126,7 +127,7 @@ namespace System.Linq.Parallel
                 AsynchronousChannel<T> current = _channels[currChannelIndex];
 
                 bool isDone = _done[currChannelIndex];
-                if (!isDone && current.TryDequeue(ref _currentElement))
+                if (!isDone && current.TryDequeue(ref _currentElement!)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
                 {
                     // The channel has an item to be processed. We already remembered the current
                     // element (Dequeue stores it as an out-parameter), so we just return true
@@ -146,7 +147,7 @@ namespace System.Linq.Parallel
                         // we still need to continue processing them.
                         if (!current.IsChunkBufferEmpty)
                         {
-                            bool dequeueResult = current.TryDequeue(ref _currentElement);
+                            bool dequeueResult = current.TryDequeue(ref _currentElement!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
                             Debug.Assert(dequeueResult, "channel isn't empty, yet the dequeue failed, hmm");
                             return true;
                         }
@@ -191,7 +192,7 @@ namespace System.Linq.Parallel
                             for (int i = 0; i < _channels.Length; i++)
                             {
                                 bool channelIsDone = false;
-                                if (!_done[i] && _channels[i].TryDequeue(ref _currentElement, ref channelIsDone))
+                                if (!_done[i] && _channels[i].TryDequeue(ref _currentElement!, ref channelIsDone)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2872
                                 {
                                     // The channel has received an item since the last time we checked.
                                     // Just return and let the consumer process the element returned.
@@ -220,6 +221,7 @@ namespace System.Linq.Parallel
                                 break;
                             }
 
+                            Debug.Assert(_consumerEvent != null);
                             //This Wait() does not require cancellation support as it will wake up when all the producers into the
                             //channel have finished.  Hence, if all the producers wake up on cancellation, so will this.
                             _consumerEvent.Wait();
index 3ede137a293eedab3f589539c9bdf5a4ca315dd0..d544f4283457e8b5c51ae048050eb1976d38e3a0 100644 (file)
@@ -28,9 +28,9 @@ namespace System.Linq.Parallel
     {
         private readonly QueryTaskGroupState _taskGroupState; // State shared among tasks.
         private readonly PartitionedStream<TInputOutput, TIgnoreKey> _partitions; // Source partitions.
-        private readonly AsynchronousChannel<TInputOutput>[] _asyncChannels; // Destination channels (async).
-        private readonly SynchronousChannel<TInputOutput>[] _syncChannels; // Destination channels (sync).
-        private readonly IEnumerator<TInputOutput> _channelEnumerator; // Output enumerator.
+        private readonly AsynchronousChannel<TInputOutput>[]? _asyncChannels; // Destination channels (async).
+        private readonly SynchronousChannel<TInputOutput>[]? _syncChannels; // Destination channels (sync).
+        private readonly IEnumerator<TInputOutput>? _channelEnumerator; // Output enumerator.
         private readonly TaskScheduler _taskScheduler; // The task manager to execute the query.
         private readonly bool _ignoreOutput; // Whether we're enumerating "for effect".
 
@@ -125,7 +125,7 @@ namespace System.Linq.Parallel
         IEnumerator<TInputOutput> IMergeHelper<TInputOutput>.GetEnumerator()
         {
             Debug.Assert(_ignoreOutput || _channelEnumerator != null);
-            return _channelEnumerator;
+            return _channelEnumerator!;
         }
 
         //-----------------------------------------------------------------------------------
index 79d3b8065e4397f7df0519167eabbda4ffe1caae..9e4388e50c86f298226559ba2699270459104e04 100644 (file)
@@ -26,6 +26,6 @@ namespace System.Linq.Parallel
         IEnumerator<TInputOutput> GetEnumerator();
 
         // Returns the merged output as an array.
-        TInputOutput[] GetResultsAsArray();
+        TInputOutput[]? GetResultsAsArray();
     }
 }
index 36ec94594102d471e8bb656da30f97dab3d7fea4..d3ba14f0952ca83e2b69daf6b041884a57e59882 100644 (file)
@@ -44,7 +44,7 @@ namespace System.Linq.Parallel
         // Straightforward IEnumerator<T> methods. So subclasses needn't bother.
         //
 
-        object IEnumerator.Current
+        object? IEnumerator.Current
         {
             get { return ((IEnumerator<TInputOutput>)this).Current; }
         }
index 44c98faab3eaae7034f1fbe0f006bc0f4a693146..3b1ed09afd678a53eec9dd0be45981dd7f5cadb8 100644 (file)
@@ -28,7 +28,7 @@ namespace System.Linq.Parallel
     {
         // Many internal algorithms are parameterized based on the data. The IMergeHelper
         // is the pluggable interface whose implementations perform those algorithms.
-        private IMergeHelper<TInputOutput> _mergeHelper;
+        private IMergeHelper<TInputOutput>? _mergeHelper;
 
         // Private constructor. MergeExecutor should only be constructed via the
         // MergeExecutor.Execute static method.
@@ -123,8 +123,9 @@ namespace System.Linq.Parallel
         // Returns the merged results as an array.
         //
 
-        internal TInputOutput[] GetResultsAsArray()
+        internal TInputOutput[]? GetResultsAsArray()
         {
+            Debug.Assert(_mergeHelper != null);
             return _mergeHelper.GetResultsAsArray();
         }
 
@@ -140,7 +141,7 @@ namespace System.Linq.Parallel
         //     An array of asynchronous channels, one for each partition.
         //
 
-        internal static AsynchronousChannel<TInputOutput>[] MakeAsynchronousChannels(int partitionCount, ParallelMergeOptions options, IntValueEvent consumerEvent, CancellationToken cancellationToken)
+        internal static AsynchronousChannel<TInputOutput>[] MakeAsynchronousChannels(int partitionCount, ParallelMergeOptions options, IntValueEvent? consumerEvent, CancellationToken cancellationToken)
         {
             AsynchronousChannel<TInputOutput>[] channels = new AsynchronousChannel<TInputOutput>[partitionCount];
 
index cfcc78db573756e0822616c3b034eb576912ffb0..93e324fee3c578f034458f659d90322ee1bcd6e2 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     {
         private readonly QueryTaskGroupState _taskGroupState; // State shared among tasks.
         private readonly PartitionedStream<TInputOutput, TKey> _partitions; // Source partitions.
-        private readonly Shared<TInputOutput[]> _results; // The array where results are stored.
+        private readonly Shared<TInputOutput[]?> _results; // The array where results are stored.
         private readonly TaskScheduler _taskScheduler; // The task manager to execute the query.
 
         //-----------------------------------------------------------------------------------
@@ -45,7 +45,7 @@ namespace System.Linq.Parallel
 
             _taskGroupState = new QueryTaskGroupState(cancellationState, queryId);
             _partitions = partitions;
-            _results = new Shared<TInputOutput[]>(null);
+            _results = new Shared<TInputOutput[]?>(null);
             _taskScheduler = taskScheduler;
         }
 
@@ -76,7 +76,7 @@ namespace System.Linq.Parallel
         // Returns the results as an array.
         //
 
-        public TInputOutput[] GetResultsAsArray()
+        public TInputOutput[]? GetResultsAsArray()
         {
             return _results.Value;
         }
index 4b58ce1c47bf33d67a75f9b28c6e6cf22e9f2bc9..2587ed422588e9011b62681d342c007226597a9e 100644 (file)
@@ -234,7 +234,7 @@ namespace System.Linq.Parallel
             ///
             /// Read and written by the consumer only.
             /// </summary>
-            private readonly Queue<Pair<TKey, TOutput>>[] _privateBuffer;
+            private readonly Queue<Pair<TKey, TOutput>>?[] _privateBuffer;
 
             /// <summary>
             /// Tracks whether MoveNext() has already been called previously.
@@ -460,7 +460,7 @@ namespace System.Linq.Parallel
                         return true;
                     }
 
-                    Debug.Assert(_privateBuffer[producer].Count == 0);
+                    Debug.Assert(_privateBuffer[producer]!.Count == 0);
                     _privateBuffer[producer] = null;
                 }
 
index ba2f1c2ee6e8eb5cfecba65d5b54bbfaf348779d..5835677d7673937afa0f4c18b8be8006ea92b271 100644 (file)
@@ -9,6 +9,7 @@
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -24,7 +25,7 @@ namespace System.Linq.Parallel
     {
         private readonly SynchronousChannel<T>[] _channels; // The channel array we will enumerate, from left-to-right.
         private int _channelIndex; // The current channel index. This moves through the array as we enumerate.
-        private T _currentElement; // The last element remembered during enumeration.
+        private T _currentElement = default!; // The last element remembered during enumeration.
 
         //-----------------------------------------------------------------------------------
         // Instantiates a new enumerator for a set of channels.
index dd84479fb75d30fe3ca950a9c2a1a1e36ebb6689..9b13c9231ff8ccc9438059c97bbc1fef7df39957 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -28,18 +29,18 @@ namespace System.Linq.Parallel
 
         private readonly int _partitionCount; // The number of partitions.
         private readonly int _partitionIndex; // Our unique partition index.
-        private readonly Func<TInputOutput, THashKey> _keySelector; // A key-selector function.
+        private readonly Func<TInputOutput, THashKey>? _keySelector; // A key-selector function.
         private readonly HashRepartitionStream<TInputOutput, THashKey, int> _repartitionStream; // A repartitioning stream.
         private readonly ListChunk<Pair<TInputOutput, THashKey>>[][] _valueExchangeMatrix; // Matrix to do inter-task communication.
         private readonly QueryOperatorEnumerator<TInputOutput, TIgnoreKey> _source; // The immediate source of data.
         private CountdownEvent _barrier; // Used to signal and wait for repartitions to complete.
         private readonly CancellationToken _cancellationToken; // A token for canceling the process.
-        private Mutables _mutables; // Mutable fields for this enumerator.
+        private Mutables? _mutables; // Mutable fields for this enumerator.
 
         private class Mutables
         {
             internal int _currentBufferIndex; // Current buffer index.
-            internal ListChunk<Pair<TInputOutput, THashKey>> _currentBuffer; // The buffer we're currently enumerating.
+            internal ListChunk<Pair<TInputOutput, THashKey>>? _currentBuffer; // The buffer we're currently enumerating.
             internal int _currentIndex; // Current index into the buffer.
 
             internal Mutables()
@@ -63,7 +64,7 @@ namespace System.Linq.Parallel
 
         internal HashRepartitionEnumerator(
             QueryOperatorEnumerator<TInputOutput, TIgnoreKey> source, int partitionCount, int partitionIndex,
-            Func<TInputOutput, THashKey> keySelector, HashRepartitionStream<TInputOutput, THashKey, int> repartitionStream,
+            Func<TInputOutput, THashKey>? keySelector, HashRepartitionStream<TInputOutput, THashKey, int> repartitionStream,
             CountdownEvent barrier, ListChunk<Pair<TInputOutput, THashKey>>[][] valueExchangeMatrix, CancellationToken cancellationToken)
         {
             Debug.Assert(source != null);
@@ -106,21 +107,21 @@ namespace System.Linq.Parallel
             if (_partitionCount == 1)
             {
                 // If there's only one partition, no need to do any sort of exchanges.
-                TIgnoreKey keyUnused = default(TIgnoreKey);
-                TInputOutput current = default(TInputOutput);
+                TIgnoreKey keyUnused = default(TIgnoreKey)!;
+                TInputOutput current = default(TInputOutput)!;
 #if DEBUG
                 currentKey = unchecked((int)0xdeadbeef);
 #endif
-                if (_source.MoveNext(ref current, ref keyUnused))
+                if (_source.MoveNext(ref current!, ref keyUnused))
                 {
                     currentElement = new Pair<TInputOutput, THashKey>(
-                        current, _keySelector == null ? default(THashKey) : _keySelector(current));
+                        current, _keySelector == null ? default : _keySelector(current));
                     return true;
                 }
                 return false;
             }
 
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             if (mutables == null)
                 mutables = _mutables = new Mutables();
 
@@ -195,15 +196,15 @@ namespace System.Linq.Parallel
 
         private void EnumerateAndRedistributeElements()
         {
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             Debug.Assert(mutables != null);
 
             ListChunk<Pair<TInputOutput, THashKey>>[] privateBuffers = new ListChunk<Pair<TInputOutput, THashKey>>[_partitionCount];
 
-            TInputOutput element = default(TInputOutput);
-            TIgnoreKey ignoreKey = default(TIgnoreKey);
+            TInputOutput element = default(TInputOutput)!;
+            TIgnoreKey ignoreKey = default(TIgnoreKey)!;
             int loopCount = 0;
-            while (_source.MoveNext(ref element, ref ignoreKey))
+            while (_source.MoveNext(ref element!, ref ignoreKey))
             {
                 if ((loopCount++ & CancellationState.POLL_INTERVAL) == 0)
                     CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -211,7 +212,7 @@ namespace System.Linq.Parallel
                 // Calculate the element's destination partition index, placing it into the
                 // appropriate buffer from which partitions will later enumerate.
                 int destinationIndex;
-                THashKey elementHashKey = default(THashKey);
+                THashKey elementHashKey = default(THashKey)!;
                 if (_keySelector != null)
                 {
                     elementHashKey = _keySelector(element);
@@ -267,7 +268,7 @@ namespace System.Linq.Parallel
                 if (_mutables == null || (_mutables._currentBufferIndex == ENUMERATION_NOT_STARTED))
                 {
                     _barrier.Signal();
-                    _barrier = null;
+                    _barrier = null!;
                 }
 
                 _source.Dispose();
index ca747ecf7d92c65d6100371f22ba7aba22ec453b..0314d2bac607428e1c5b9f9482f3520289d7863f 100644 (file)
@@ -34,8 +34,8 @@ namespace System.Linq.Parallel
     /// <typeparam name="TOrderKey"></typeparam>
     internal abstract class HashRepartitionStream<TInputOutput, THashKey, TOrderKey> : PartitionedStream<Pair<TInputOutput, THashKey>, TOrderKey>
     {
-        private readonly IEqualityComparer<THashKey> _keyComparer; // The optional key comparison routine.
-        private readonly IEqualityComparer<TInputOutput> _elementComparer; // The optional element comparison routine.
+        private readonly IEqualityComparer<THashKey>? _keyComparer; // The optional key comparison routine.
+        private readonly IEqualityComparer<TInputOutput>? _elementComparer; // The optional element comparison routine.
         private readonly int _distributionMod; // The distribution value we'll use to scramble input.
 
         //---------------------------------------------------------------------------------------
@@ -43,8 +43,8 @@ namespace System.Linq.Parallel
         //
 
         internal HashRepartitionStream(
-            int partitionsCount, IComparer<TOrderKey> orderKeyComparer, IEqualityComparer<THashKey> hashKeyComparer,
-            IEqualityComparer<TInputOutput> elementComparer)
+            int partitionsCount, IComparer<TOrderKey> orderKeyComparer, IEqualityComparer<THashKey>? hashKeyComparer,
+            IEqualityComparer<TInputOutput>? elementComparer)
             : base(partitionsCount, orderKeyComparer, OrdinalIndexState.Shuffled)
         {
             // elementComparer is used by operators that use elements themselves as the hash keys.
index 218603e60dc66b3deea4982d7246f9db958200a0..2acfec7741d7e557d4cd5f63eeb7432ef9ecabd2 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -28,20 +29,20 @@ namespace System.Linq.Parallel
 
         private readonly int _partitionCount; // The number of partitions.
         private readonly int _partitionIndex; // Our unique partition index.
-        private readonly Func<TInputOutput, THashKey> _keySelector; // A key-selector function.
+        private readonly Func<TInputOutput, THashKey>? _keySelector; // A key-selector function.
         private readonly HashRepartitionStream<TInputOutput, THashKey, TOrderKey> _repartitionStream; // A repartitioning stream.
         private readonly ListChunk<Pair<TInputOutput, THashKey>>[][] _valueExchangeMatrix; // Matrix to do inter-task communication of values.
         private readonly ListChunk<TOrderKey>[][] _keyExchangeMatrix; // Matrix to do inter-task communication of order keys.
         private readonly QueryOperatorEnumerator<TInputOutput, TOrderKey> _source; // The immediate source of data.
         private CountdownEvent _barrier; // Used to signal and wait for repartitions to complete.
         private readonly CancellationToken _cancellationToken; // A token for canceling the process.
-        private Mutables _mutables; // Mutable fields for this enumerator.
+        private Mutables? _mutables; // Mutable fields for this enumerator.
 
         private class Mutables
         {
             internal int _currentBufferIndex; // Current buffer index.
-            internal ListChunk<Pair<TInputOutput, THashKey>> _currentBuffer; // The buffer we're currently enumerating.
-            internal ListChunk<TOrderKey> _currentKeyBuffer; // The buffer we're currently enumerating.
+            internal ListChunk<Pair<TInputOutput, THashKey>>? _currentBuffer; // The buffer we're currently enumerating.
+            internal ListChunk<TOrderKey>? _currentKeyBuffer; // The buffer we're currently enumerating.
             internal int _currentIndex; // Current index into the buffer.
 
             internal Mutables()
@@ -65,7 +66,7 @@ namespace System.Linq.Parallel
 
         internal OrderedHashRepartitionEnumerator(
             QueryOperatorEnumerator<TInputOutput, TOrderKey> source, int partitionCount, int partitionIndex,
-            Func<TInputOutput, THashKey> keySelector, OrderedHashRepartitionStream<TInputOutput, THashKey, TOrderKey> repartitionStream, CountdownEvent barrier,
+            Func<TInputOutput, THashKey>? keySelector, OrderedHashRepartitionStream<TInputOutput, THashKey, TOrderKey> repartitionStream, CountdownEvent barrier,
             ListChunk<Pair<TInputOutput, THashKey>>[][] valueExchangeMatrix, ListChunk<TOrderKey>[][] keyExchangeMatrix, CancellationToken cancellationToken)
         {
             Debug.Assert(source != null);
@@ -108,20 +109,20 @@ namespace System.Linq.Parallel
         {
             if (_partitionCount == 1)
             {
-                TInputOutput current = default(TInputOutput);
+                TInputOutput current = default(TInputOutput)!;
 
                 // If there's only one partition, no need to do any sort of exchanges.
-                if (_source.MoveNext(ref current, ref currentKey))
+                if (_source.MoveNext(ref current!, ref currentKey))
                 {
                     currentElement = new Pair<TInputOutput, THashKey>(
-                        current, _keySelector == null ? default(THashKey) : _keySelector(current));
+                        current, _keySelector == null ? default : _keySelector(current));
                     return true;
                 }
 
                 return false;
             }
 
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             if (mutables == null)
                 mutables = _mutables = new Mutables();
 
@@ -160,7 +161,7 @@ namespace System.Linq.Parallel
                         mutables._currentKeyBuffer = mutables._currentKeyBuffer.Next;
                         Debug.Assert(mutables._currentBuffer == null || mutables._currentBuffer.Count > 0);
                         Debug.Assert((mutables._currentBuffer == null) == (mutables._currentKeyBuffer == null));
-                        Debug.Assert(mutables._currentBuffer == null || mutables._currentBuffer.Count == mutables._currentKeyBuffer.Count);
+                        Debug.Assert(mutables._currentBuffer == null || mutables._currentBuffer.Count == mutables._currentKeyBuffer!.Count);
                         continue; // Go back around and invoke this same logic.
                     }
                 }
@@ -204,16 +205,16 @@ namespace System.Linq.Parallel
 
         private void EnumerateAndRedistributeElements()
         {
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             Debug.Assert(mutables != null);
 
             ListChunk<Pair<TInputOutput, THashKey>>[] privateBuffers = new ListChunk<Pair<TInputOutput, THashKey>>[_partitionCount];
             ListChunk<TOrderKey>[] privateKeyBuffers = new ListChunk<TOrderKey>[_partitionCount];
 
-            TInputOutput element = default(TInputOutput);
-            TOrderKey key = default(TOrderKey);
+            TInputOutput element = default(TInputOutput)!;
+            TOrderKey key = default(TOrderKey)!;
             int loopCount = 0;
-            while (_source.MoveNext(ref element, ref key))
+            while (_source.MoveNext(ref element!, ref key))
             {
                 if ((loopCount++ & CancellationState.POLL_INTERVAL) == 0)
                     CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -221,7 +222,7 @@ namespace System.Linq.Parallel
                 // Calculate the element's destination partition index, placing it into the
                 // appropriate buffer from which partitions will later enumerate.
                 int destinationIndex;
-                THashKey elementHashKey = default(THashKey);
+                THashKey elementHashKey = default(THashKey)!;
                 if (_keySelector != null)
                 {
                     elementHashKey = _keySelector(element);
@@ -283,7 +284,7 @@ namespace System.Linq.Parallel
                 if (_mutables == null || (_mutables._currentBufferIndex == ENUMERATION_NOT_STARTED))
                 {
                     _barrier.Signal();
-                    _barrier = null;
+                    _barrier = null!;
                 }
 
                 _source.Dispose();
index 555b731620733dc8a185f1f7e1b52b26e659f6d3..62f9ebc2892f305059afac5de781e4ea93c97e35 100644 (file)
@@ -16,8 +16,8 @@ namespace System.Linq.Parallel
     internal class OrderedHashRepartitionStream<TInputOutput, THashKey, TOrderKey> : HashRepartitionStream<TInputOutput, THashKey, TOrderKey>
     {
         internal OrderedHashRepartitionStream(
-            PartitionedStream<TInputOutput, TOrderKey> inputStream, Func<TInputOutput, THashKey> hashKeySelector,
-            IEqualityComparer<THashKey> hashKeyComparer, IEqualityComparer<TInputOutput> elementComparer, CancellationToken cancellationToken)
+            PartitionedStream<TInputOutput, TOrderKey> inputStream, Func<TInputOutput, THashKey>? hashKeySelector,
+            IEqualityComparer<THashKey>? hashKeyComparer, IEqualityComparer<TInputOutput>? elementComparer, CancellationToken cancellationToken)
             : base(inputStream.PartitionCount, inputStream.KeyComparer, hashKeyComparer, elementComparer)
         {
             _partitions =
index a4920c237a7123e6262036f863c5c758c63a0e19..a992fff2cff02474993a88466740e3cf12f69803 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -75,21 +76,19 @@ namespace System.Linq.Parallel
             Debug.Assert(partitionCount > 0);
 
             // If this is a wrapper, grab the internal wrapped data source so we can uncover its real type.
-            ParallelEnumerableWrapper<T> wrapper = source as ParallelEnumerableWrapper<T>;
-            if (wrapper != null)
+            if (source is ParallelEnumerableWrapper<T> wrapper)
             {
                 source = wrapper.WrappedEnumerable;
                 Debug.Assert(source != null);
             }
 
             // Check whether we have an indexable data source.
-            IList<T> sourceAsList = source as IList<T>;
-            if (sourceAsList != null)
+            if (source is IList<T> sourceAsList)
             {
                 QueryOperatorEnumerator<T, int>[] partitions = new QueryOperatorEnumerator<T, int>[partitionCount];
 
                 // We use this below to specialize enumerators when possible.
-                T[] sourceAsArray = source as T[];
+                T[]? sourceAsArray = source as T[];
 
                 // If range partitioning is used, chunk size will be unlimited, i.e. -1.
                 int maxChunkSize = -1;
@@ -219,7 +218,7 @@ namespace System.Linq.Parallel
             private readonly int _partitionIndex; // The index of the current partition.
             private readonly int _maxChunkSize; // The maximum size of a chunk. -1 if unlimited.
             private readonly int _sectionCount; // Precomputed in ctor: the number of sections the range is split into.
-            private Mutables _mutables; // Lazily allocated mutable variables.
+            private Mutables? _mutables; // Lazily allocated mutable variables.
 
             private class Mutables
             {
@@ -257,10 +256,10 @@ namespace System.Linq.Parallel
                     ((_elementCount % sectionSize) == 0 ? 0 : 1);
             }
 
-            internal override bool MoveNext(ref T currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
             {
                 // Lazily allocate the mutable holder.
-                Mutables mutables = _mutables;
+                Mutables? mutables = _mutables;
                 if (mutables == null)
                 {
                     mutables = _mutables = new Mutables();
@@ -279,7 +278,7 @@ namespace System.Linq.Parallel
 
             private bool MoveNextSlowPath()
             {
-                Mutables mutables = _mutables;
+                Mutables? mutables = _mutables;
                 Debug.Assert(mutables != null);
                 Debug.Assert(mutables._currentPositionInChunk >= mutables._currentChunkSize);
 
@@ -339,7 +338,7 @@ namespace System.Linq.Parallel
             private readonly T[] _data; // The elements to iterate over.
             private readonly int _startIndex; // Where to begin iterating.
             private readonly int _maximumIndex; // The maximum index to iterate over.
-            private Shared<int> _currentIndex; // The current index (lazily allocated).
+            private Shared<int>? _currentIndex; // The current index (lazily allocated).
 
             internal ArrayContiguousIndexRangeEnumerator(T[] data, int partitionCount, int partitionIndex)
             {
@@ -366,7 +365,7 @@ namespace System.Linq.Parallel
                 Debug.Assert(_currentIndex == null, "Expected deferred allocation to ensure it happens on correct thread");
             }
 
-            internal override bool MoveNext(ref T currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
             {
                 // Lazily allocate the current index if needed.
                 if (_currentIndex == null)
@@ -397,7 +396,7 @@ namespace System.Linq.Parallel
             private readonly int _partitionIndex; // The index of the current partition.
             private readonly int _maxChunkSize; // The maximum size of a chunk. -1 if unlimited.
             private readonly int _sectionCount; // Precomputed in ctor: the number of sections the range is split into.
-            private Mutables _mutables; // Lazily allocated mutable variables.
+            private Mutables? _mutables; // Lazily allocated mutable variables.
 
             private class Mutables
             {
@@ -435,10 +434,10 @@ namespace System.Linq.Parallel
                     ((_elementCount % sectionSize) == 0 ? 0 : 1);
             }
 
-            internal override bool MoveNext(ref T currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
             {
                 // Lazily allocate the mutable holder.
-                Mutables mutables = _mutables;
+                Mutables? mutables = _mutables;
                 if (mutables == null)
                 {
                     mutables = _mutables = new Mutables();
@@ -457,7 +456,7 @@ namespace System.Linq.Parallel
 
             private bool MoveNextSlowPath()
             {
-                Mutables mutables = _mutables;
+                Mutables? mutables = _mutables;
                 Debug.Assert(mutables != null);
                 Debug.Assert(mutables._currentPositionInChunk >= mutables._currentChunkSize);
 
@@ -517,7 +516,7 @@ namespace System.Linq.Parallel
             private readonly IList<T> _data; // The elements to iterate over.
             private readonly int _startIndex; // Where to begin iterating.
             private readonly int _maximumIndex; // The maximum index to iterate over.
-            private Shared<int> _currentIndex; // The current index (lazily allocated).
+            private Shared<int>? _currentIndex; // The current index (lazily allocated).
 
             internal ListContiguousIndexRangeEnumerator(IList<T> data, int partitionCount, int partitionIndex)
             {
@@ -544,7 +543,7 @@ namespace System.Linq.Parallel
                 Debug.Assert(_currentIndex == null, "Expected deferred allocation to ensure it happens on correct thread");
             }
 
-            internal override bool MoveNext(ref T currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
             {
                 // Lazily allocate the current index if needed.
                 if (_currentIndex == null)
@@ -579,7 +578,7 @@ namespace System.Linq.Parallel
             private readonly Shared<int> _currentIndex; // The index shared by all.
             private readonly Shared<int> _activeEnumeratorsCount; // How many enumerators over the same source have not been disposed yet?
             private readonly Shared<bool> _exceptionTracker;
-            private Mutables _mutables; // Any mutable fields on this enumerator. These mutables are local and persistent
+            private Mutables? _mutables; // Any mutable fields on this enumerator. These mutables are local and persistent
 
             private class Mutables
             {
@@ -623,9 +622,9 @@ namespace System.Linq.Parallel
             // Just retrieves the current element from our current chunk.
             //
 
-            internal override bool MoveNext(ref T currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref T currentElement, ref int currentKey)
             {
-                Mutables mutables = _mutables;
+                Mutables? mutables = _mutables;
                 if (mutables == null)
                 {
                     mutables = _mutables = new Mutables();
index 5686b141d1b997ae9b8e621953ce3b62d84a370b..84d06a3118ee43e5ea3f0d13b819791c9d78fae2 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Linq.Parallel
 
         internal UnorderedHashRepartitionStream(
             PartitionedStream<TInputOutput, TIgnoreKey> inputStream,
-            Func<TInputOutput, THashKey> keySelector, IEqualityComparer<THashKey> keyComparer, IEqualityComparer<TInputOutput> elementComparer,
+            Func<TInputOutput, THashKey>? keySelector, IEqualityComparer<THashKey>? keyComparer, IEqualityComparer<TInputOutput>? elementComparer,
             CancellationToken cancellationToken)
             : base(inputStream.PartitionCount, Util.GetDefaultComparer<int>(), keyComparer, elementComparer)
         {
index 23e1087f11d6c5dcc19bc3d6449d969568d63327..dbbe16809bb88ee17bf8739df433cdceaa129f5c 100644 (file)
@@ -61,7 +61,7 @@ namespace System.Linq.Parallel
         private readonly Func<TIntermediate, TOutput> _resultSelector;
 
         // A function that constructs seed instances
-        private readonly Func<TIntermediate> _seedFactory;
+        private readonly Func<TIntermediate>? _seedFactory;
 
         //---------------------------------------------------------------------------------------
         // Constructs a new instance of an associative operator.
@@ -70,7 +70,7 @@ namespace System.Linq.Parallel
         //     This operator must be associative.
         //
 
-        internal AssociativeAggregationOperator(IEnumerable<TInput> child, TIntermediate seed, Func<TIntermediate> seedFactory, bool seedIsSpecified,
+        internal AssociativeAggregationOperator(IEnumerable<TInput> child, TIntermediate seed, Func<TIntermediate>? seedFactory, bool seedIsSpecified,
                                                 Func<TIntermediate, TInput, TIntermediate> intermediateReduce,
                                                 Func<TIntermediate, TIntermediate, TIntermediate> finalReduce,
                                                 Func<TIntermediate, TOutput> resultSelector, bool throwIfEmpty, QueryAggregationOptions options)
@@ -106,7 +106,7 @@ namespace System.Linq.Parallel
             Debug.Assert(_finalReduce != null);
             Debug.Assert(_resultSelector != null);
 
-            TIntermediate accumulator = default(TIntermediate);
+            TIntermediate accumulator = default(TIntermediate)!;
             bool hadElements = false;
 
             // Because the final reduction is typically much cheaper than the intermediate
@@ -271,7 +271,7 @@ namespace System.Linq.Parallel
             // the end, we will have our intermediate result, ready for final aggregation.
             //
 
-            internal override bool MoveNext(ref TIntermediate currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TIntermediate currentElement, ref int currentKey)
             {
                 Debug.Assert(_reduceOperator != null);
                 Debug.Assert(_reduceOperator._intermediateReduce != null, "expected a compiled operator");
@@ -284,7 +284,7 @@ namespace System.Linq.Parallel
                 _accumulated = true;
 
                 bool hadNext = false;
-                TIntermediate accumulator = default(TIntermediate);
+                TIntermediate accumulator = default(TIntermediate)!;
 
                 // Initialize the accumulator.
                 if (_reduceOperator._seedIsSpecified)
@@ -300,18 +300,18 @@ namespace System.Linq.Parallel
                     // Seed may be unspecified only if TInput is the same as TIntermediate.
                     Debug.Assert(typeof(TInput) == typeof(TIntermediate));
 
-                    TInput acc = default(TInput);
-                    TKey accKeyUnused = default(TKey);
-                    if (!_source.MoveNext(ref acc, ref accKeyUnused)) return false;
+                    TInput acc = default(TInput)!;
+                    TKey accKeyUnused = default(TKey)!;
+                    if (!_source.MoveNext(ref acc!, ref accKeyUnused)) return false;
                     hadNext = true;
-                    accumulator = (TIntermediate)((object)acc);
+                    accumulator = (TIntermediate)((object?)acc!);
                 }
 
                 // Scan through the source and accumulate the result.
-                TInput input = default(TInput);
-                TKey keyUnused = default(TKey);
+                TInput input = default(TInput)!;
+                TKey keyUnused = default(TKey)!;
                 int i = 0;
-                while (_source.MoveNext(ref input, ref keyUnused))
+                while (_source.MoveNext(ref input!, ref keyUnused))
                 {
                     if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
index 2a6e295c143f3c6ca430437c4464139119809280..b5817e153faaec1ddb733f07d7e3502fed2f1d20 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -184,7 +185,7 @@ namespace System.Linq.Parallel
             // index offset.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref ConcatKey<TLeftKey, TRightKey> currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref ConcatKey<TLeftKey, TRightKey> currentKey)
             {
                 Debug.Assert(_firstSource != null);
                 Debug.Assert(_secondSource != null);
@@ -193,8 +194,8 @@ namespace System.Linq.Parallel
                 if (!_begunSecond)
                 {
                     // If elements remain, just return true and continue enumerating the left.
-                    TLeftKey leftKey = default(TLeftKey);
-                    if (_firstSource.MoveNext(ref currentElement, ref leftKey))
+                    TLeftKey leftKey = default(TLeftKey)!;
+                    if (_firstSource.MoveNext(ref currentElement!, ref leftKey))
                     {
                         currentKey = ConcatKey<TLeftKey, TRightKey>.MakeLeft(leftKey);
                         return true;
@@ -203,8 +204,8 @@ namespace System.Linq.Parallel
                 }
 
                 // Now either move on to, or continue, enumerating the right data source.
-                TRightKey rightKey = default(TRightKey);
-                if (_secondSource.MoveNext(ref currentElement, ref rightKey))
+                TRightKey rightKey = default(TRightKey)!;
+                if (_secondSource.MoveNext(ref currentElement!, ref rightKey))
                 {
                     currentKey = ConcatKey<TLeftKey, TRightKey>.MakeRight(rightKey);
                     return true;
@@ -300,21 +301,21 @@ namespace System.Linq.Parallel
         private readonly TRightKey _rightKey;
         private readonly bool _isLeft;
 
-        private ConcatKey(TLeftKey leftKey, TRightKey rightKey, bool isLeft)
+        private ConcatKey([AllowNull] TLeftKey leftKey, [AllowNull] TRightKey rightKey, bool isLeft)
         {
             _leftKey = leftKey;
             _rightKey = rightKey;
             _isLeft = isLeft;
         }
 
-        internal static ConcatKey<TLeftKey, TRightKey> MakeLeft(TLeftKey leftKey)
+        internal static ConcatKey<TLeftKey, TRightKey> MakeLeft([AllowNull] TLeftKey leftKey)
         {
-            return new ConcatKey<TLeftKey, TRightKey>(leftKey, default(TRightKey), isLeft: true);
+            return new ConcatKey<TLeftKey, TRightKey>(leftKey, default, isLeft: true);
         }
 
-        internal static ConcatKey<TLeftKey, TRightKey> MakeRight(TRightKey rightKey)
+        internal static ConcatKey<TLeftKey, TRightKey> MakeRight([AllowNull] TRightKey rightKey)
         {
-            return new ConcatKey<TLeftKey, TRightKey>(default(TLeftKey), rightKey, isLeft: false);
+            return new ConcatKey<TLeftKey, TRightKey>(default, rightKey, isLeft: false);
         }
 
         internal static IComparer<ConcatKey<TLeftKey, TRightKey>> MakeComparer(
index 8e191f77146efe7a4620d0a94a75776bb15a6f1f..f91eab5f21168b7a614f8025c88f854a5d66aa93 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -22,13 +23,13 @@ namespace System.Linq.Parallel
     internal sealed class ExceptQueryOperator<TInputOutput> :
         BinaryQueryOperator<TInputOutput, TInputOutput, TInputOutput>
     {
-        private readonly IEqualityComparer<TInputOutput> _comparer; // An equality comparer.
+        private readonly IEqualityComparer<TInputOutput>? _comparer; // An equality comparer.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new set except operator.
         //
 
-        internal ExceptQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput> comparer)
+        internal ExceptQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput>? comparer)
             : base(left, right)
         {
             Debug.Assert(left != null && right != null, "child data sources cannot be null");
@@ -138,10 +139,10 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> _leftSource; // Left data source.
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> _rightSource; // Right data source.
-            private readonly IEqualityComparer<TInputOutput> _comparer; // A comparer used for equality checks/hash-coding.
-            private Set<TInputOutput> _hashLookup; // The hash lookup, used to produce the distinct set.
+            private readonly IEqualityComparer<TInputOutput>? _comparer; // A comparer used for equality checks/hash-coding.
+            private Set<TInputOutput>? _hashLookup; // The hash lookup, used to produce the distinct set.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount;
+            private Shared<int>? _outputLoopCount;
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new except query operator enumerator.
@@ -150,7 +151,7 @@ namespace System.Linq.Parallel
             internal ExceptQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> rightSource,
-                IEqualityComparer<TInputOutput> comparer,
+                IEqualityComparer<TInputOutput>? comparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
@@ -166,7 +167,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the distinct set
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey)
             {
                 Debug.Assert(_leftSource != null);
                 Debug.Assert(_rightSource != null);
@@ -194,8 +195,9 @@ namespace System.Linq.Parallel
 
                 // Now iterate over the right data source, looking for matches.
                 Pair<TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                TLeftKey leftKeyUnused = default(TLeftKey);
+                TLeftKey leftKeyUnused = default!;
 
+                Debug.Assert(_outputLoopCount != null);
                 while (_leftSource.MoveNext(ref leftElement, ref leftKeyUnused))
                 {
                     if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0)
@@ -227,9 +229,9 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> _leftSource; // Left data source.
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> _rightSource; // Right data source.
-            private readonly IEqualityComparer<TInputOutput> _comparer; // A comparer used for equality checks/hash-coding.
+            private readonly IEqualityComparer<TInputOutput>? _comparer; // A comparer used for equality checks/hash-coding.
             private readonly IComparer<TLeftKey> _leftKeyComparer; // A comparer for order keys.
-            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, Pair<TInputOutput, TLeftKey>>> _outputEnumerator; // The enumerator output elements + order keys.
+            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, Pair<TInputOutput, TLeftKey>>>? _outputEnumerator; // The enumerator output elements + order keys.
             private readonly CancellationToken _cancellationToken;
 
             //---------------------------------------------------------------------------------------
@@ -239,7 +241,7 @@ namespace System.Linq.Parallel
             internal OrderedExceptQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> rightSource,
-                IEqualityComparer<TInputOutput> comparer, IComparer<TLeftKey> leftKeyComparer,
+                IEqualityComparer<TInputOutput>? comparer, IComparer<TLeftKey> leftKeyComparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
@@ -256,7 +258,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the distinct set
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref TLeftKey currentKey)
             {
                 Debug.Assert(_leftSource != null);
                 Debug.Assert(_rightSource != null);
@@ -282,7 +284,7 @@ namespace System.Linq.Parallel
                             new WrapperEqualityComparer<TInputOutput>(_comparer));
 
                     Pair<TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                    TLeftKey leftKey = default(TLeftKey);
+                    TLeftKey leftKey = default!;
                     while (_leftSource.MoveNext(ref leftElement, ref leftKey))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
index 688ea6a8751133747ee22d12ad04164caa624988..beb27a819b43a1b005f7e0a305df5d882d363ba2 100644 (file)
@@ -29,7 +29,7 @@ namespace System.Linq.Parallel
         private readonly Func<TLeftInput, TKey> _leftKeySelector; // The key selection routine for the outer (left) data source.
         private readonly Func<TRightInput, TKey> _rightKeySelector; // The key selection routine for the inner (right) data source.
         private readonly Func<TLeftInput, IEnumerable<TRightInput>, TOutput> _resultSelector; // The result selection routine.
-        private readonly IEqualityComparer<TKey> _keyComparer; // An optional key comparison object.
+        private readonly IEqualityComparer<TKey>? _keyComparer; // An optional key comparison object.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new join operator.
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
                                         Func<TLeftInput, TKey> leftKeySelector,
                                         Func<TRightInput, TKey> rightKeySelector,
                                         Func<TLeftInput, IEnumerable<TRightInput>, TOutput> resultSelector,
-                                        IEqualityComparer<TKey> keyComparer)
+                                        IEqualityComparer<TKey>? keyComparer)
             : base(left, right)
         {
             Debug.Assert(left != null && right != null, "child data sources cannot be null");
@@ -136,7 +136,7 @@ namespace System.Linq.Parallel
         private void WrapPartitionedStreamHelper<TLeftKey, TRightKey>(
             PartitionedStream<Pair<TLeftInput, TKey>, TLeftKey> leftHashStream,
             HashLookupBuilder<IEnumerable<TRightInput>, TRightKey, TKey>[] rightLookupBuilders,
-            IComparer<TRightKey> rightKeyComparer, IPartitionedStreamRecipient<TOutput> outputRecipient,
+            IComparer<TRightKey>? rightKeyComparer, IPartitionedStreamRecipient<TOutput> outputRecipient,
             int partitionCount, CancellationToken cancellationToken)
         {
             if (RightChild.OutputOrdered && LeftChild.OutputOrdered)
@@ -218,9 +218,9 @@ namespace System.Linq.Parallel
     internal class GroupJoinHashLookupBuilder<TElement, TOrderKey, THashKey> : HashLookupBuilder<IEnumerable<TElement>, int, THashKey>
     {
         private readonly QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> _dataSource; // data source. For building.
-        private readonly IEqualityComparer<THashKey> _keyComparer; // An optional key comparison object.
+        private readonly IEqualityComparer<THashKey>? _keyComparer; // An optional key comparison object.
 
-        internal GroupJoinHashLookupBuilder(QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> dataSource, IEqualityComparer<THashKey> keyComparer)
+        internal GroupJoinHashLookupBuilder(QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> dataSource, IEqualityComparer<THashKey>? keyComparer)
         {
             Debug.Assert(dataSource != null);
 
@@ -257,7 +257,7 @@ namespace System.Linq.Parallel
             {
                 bool hasCollision = true;
 
-                ListChunk<TElement> currentValue = default(ListChunk<TElement>);
+                ListChunk<TElement>? currentValue = default(ListChunk<TElement>);
                 if (!_base.TryGetValue(hashKey, ref currentValue))
                 {
                     const int INITIAL_CHUNK_SIZE = 2;
@@ -304,12 +304,12 @@ namespace System.Linq.Parallel
     internal sealed class OrderedGroupJoinHashLookupBuilder<TElement, TOrderKey, THashKey> : HashLookupBuilder<IEnumerable<TElement>, Pair<bool, TOrderKey>, THashKey>
     {
         private readonly QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> _dataSource; // data source. For building.
-        private readonly IEqualityComparer<THashKey> _keyComparer; // An optional key comparison object.
+        private readonly IEqualityComparer<THashKey>? _keyComparer; // An optional key comparison object.
         private readonly IComparer<TOrderKey> _orderKeyComparer;
 
         internal OrderedGroupJoinHashLookupBuilder(
             QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> dataSource,
-            IEqualityComparer<THashKey> keyComparer,
+            IEqualityComparer<THashKey>? keyComparer,
             IComparer<TOrderKey> orderKeyComparer)
         {
             Debug.Assert(dataSource != null);
@@ -362,7 +362,7 @@ namespace System.Linq.Parallel
             {
                 bool hasCollision = true;
 
-                GroupKeyData currentValue = default(GroupKeyData);
+                GroupKeyData? currentValue = default(GroupKeyData);
                 if (!_base.TryGetValue(hashKey, ref currentValue))
                 {
                     currentValue = new GroupKeyData(orderKey, hashKey, _orderKeyComparer);
@@ -446,8 +446,8 @@ namespace System.Linq.Parallel
 
         private Pair<IEnumerable<TElement>, TOrderKey> GetValueList(THashKey key)
         {
-            TBaseElement baseValue = default(TBaseElement);
-            if (_base.TryGetValue(key, ref baseValue))
+            TBaseElement baseValue = default(TBaseElement)!;
+            if (_base.TryGetValue(key, ref baseValue!))
             {
                 return CreateValuePair(baseValue);
             }
index d36f6a40956ca2059223eaf61aaa4581f9053297..076213f247a2c8a03f031be96703965f7ecac34f 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -43,14 +44,14 @@ namespace System.Linq.Parallel
         private readonly Func<TLeftInput, TRightInput, TOutput> _resultSelector; // Result selector.
         private readonly HashJoinOutputKeyBuilder<TLeftKey, TRightKey, TOutputKey> _outputKeyBuilder;
         private readonly CancellationToken _cancellationToken;
-        private Mutables _mutables;
+        private Mutables? _mutables;
 
         private class Mutables
         {
-            internal TLeftInput _currentLeft; // The current matching left element.
-            internal TLeftKey _currentLeftKey; // The current index of the matching left element.
-            internal HashJoinHashLookup<THashKey, TRightInput, TRightKey> _rightHashLookup; // The hash lookup.
-            internal ListChunk<Pair<TRightInput, TRightKey>> _currentRightMatches; // Current right matches (if any).
+            internal TLeftInput _currentLeft = default!; // The current matching left element.
+            internal TLeftKey _currentLeftKey = default!; // The current index of the matching left element.
+            internal HashJoinHashLookup<THashKey, TRightInput, TRightKey>? _rightHashLookup; // The hash lookup.
+            internal ListChunk<Pair<TRightInput, TRightKey>>? _currentRightMatches; // Current right matches (if any).
             internal int _currentRightMatchesIndex; // Current index in the set of right matches.
             internal int _outputLoopCount;
         }
@@ -90,14 +91,14 @@ namespace System.Linq.Parallel
         // as we do for inner joins.
         //
 
-        internal override bool MoveNext(ref TOutput currentElement, ref TOutputKey currentKey)
+        internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TOutput currentElement, ref TOutputKey currentKey)
         {
             Debug.Assert(_resultSelector != null, "expected a compiled result selector");
             Debug.Assert(_leftSource != null);
             Debug.Assert(_rightLookupBuilder != null);
 
             // BUILD phase: If we haven't built the hash-table yet, create that first.
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             if (mutables == null)
             {
                 mutables = _mutables = new Mutables();
@@ -105,7 +106,7 @@ namespace System.Linq.Parallel
             }
 
             // PROBE phase: So long as the source has a next element, return the match.
-            ListChunk<Pair<TRightInput, TRightKey>> currentRightChunk = mutables._currentRightMatches;
+            ListChunk<Pair<TRightInput, TRightKey>>? currentRightChunk = mutables._currentRightMatches;
             if (currentRightChunk != null && mutables._currentRightMatchesIndex == currentRightChunk.Count)
             {
                 mutables._currentRightMatches = currentRightChunk.Next;
@@ -116,7 +117,7 @@ namespace System.Linq.Parallel
             {
                 // We have to look up the next list of matches in the hash-table.
                 Pair<TLeftInput, THashKey> leftPair = default(Pair<TLeftInput, THashKey>);
-                TLeftKey leftKey = default(TLeftKey);
+                TLeftKey leftKey = default(TLeftKey)!;
                 while (_leftSource.MoveNext(ref leftPair, ref leftKey))
                 {
                     if ((mutables._outputLoopCount++ & CancellationState.POLL_INTERVAL) == 0)
@@ -130,6 +131,7 @@ namespace System.Linq.Parallel
                     // Ignore null keys.
                     if (leftHashKey != null)
                     {
+                        Debug.Assert(mutables._rightHashLookup != null);
                         if (mutables._rightHashLookup.TryGetValue(leftHashKey, ref matchValue))
                         {
                             // We found a new match. We remember the list in case there are multiple
@@ -245,7 +247,7 @@ namespace System.Linq.Parallel
 #endif
 
             Pair<TBaseElement, THashKey> currentPair = default(Pair<TBaseElement, THashKey>);
-            TBaseOrderKey orderKey = default(TBaseOrderKey);
+            TBaseOrderKey orderKey = default(TBaseOrderKey)!;
             int i = 0;
             while (dataSource.MoveNext(ref currentPair, ref orderKey))
             {
@@ -337,14 +339,14 @@ namespace System.Linq.Parallel
         }
         private readonly Pair<TElement, TOrderKey> _head;
 
-        internal ListChunk<Pair<TElement, TOrderKey>> Tail
+        internal ListChunk<Pair<TElement, TOrderKey>>? Tail
         {
             get
             {
                 return _tail;
             }
         }
-        private ListChunk<Pair<TElement, TOrderKey>> _tail;
+        private ListChunk<Pair<TElement, TOrderKey>>? _tail;
 
         private const int INITIAL_CHUNK_SIZE = 2;
 
@@ -374,7 +376,7 @@ namespace System.Linq.Parallel
             {
                 _tail = new ListChunk<Pair<TElement, TOrderKey>>(INITIAL_CHUNK_SIZE);
             }
-            _tail.Add(CreatePair(value, orderKey));
+            _tail!.Add(CreatePair(value, orderKey));
 
             return requiresMemoryChange;
         }
index 1073768072743c70ac7ccc0a1c9bf9d6227143b5..1a1799b1aa6752c9b251e5d032a0e6d0b0e7ac2c 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -21,13 +22,13 @@ namespace System.Linq.Parallel
     internal sealed class IntersectQueryOperator<TInputOutput> :
         BinaryQueryOperator<TInputOutput, TInputOutput, TInputOutput>
     {
-        private readonly IEqualityComparer<TInputOutput> _comparer; // An equality comparer.
+        private readonly IEqualityComparer<TInputOutput>? _comparer; // An equality comparer.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new intersection operator.
         //
 
-        internal IntersectQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput> comparer)
+        internal IntersectQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput>? comparer)
             : base(left, right)
         {
             Debug.Assert(left != null && right != null, "child data sources cannot be null");
@@ -127,10 +128,10 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> _leftSource; // Left data source.
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> _rightSource; // Right data source.
-            private readonly IEqualityComparer<TInputOutput> _comparer; // Comparer to use for equality/hash-coding.
-            private Set<TInputOutput> _hashLookup; // The hash lookup, used to produce the intersection.
+            private readonly IEqualityComparer<TInputOutput>? _comparer; // Comparer to use for equality/hash-coding.
+            private Set<TInputOutput>? _hashLookup; // The hash lookup, used to produce the intersection.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount;
+            private Shared<int>? _outputLoopCount;
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new intersection operator.
@@ -139,7 +140,7 @@ namespace System.Linq.Parallel
             internal IntersectQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> rightSource,
-                IEqualityComparer<TInputOutput> comparer, CancellationToken cancellationToken)
+                IEqualityComparer<TInputOutput>? comparer, CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
                 Debug.Assert(rightSource != null);
@@ -154,7 +155,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the intersection.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey)
             {
                 Debug.Assert(_leftSource != null);
                 Debug.Assert(_rightSource != null);
@@ -181,10 +182,11 @@ namespace System.Linq.Parallel
 
                 // Now iterate over the left data source, looking for matches.
                 Pair<TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                TLeftKey keyUnused = default(TLeftKey);
+                TLeftKey keyUnused = default(TLeftKey)!;
 
                 while (_leftSource.MoveNext(ref leftElement, ref keyUnused))
                 {
+                    Debug.Assert(_outputLoopCount != null);
                     if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
 
@@ -230,7 +232,7 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> _rightSource; // Right data source.
             private readonly IEqualityComparer<Wrapper<TInputOutput>> _comparer; // Comparer to use for equality/hash-coding.
             private readonly IComparer<TLeftKey> _leftKeyComparer; // Comparer to use to determine ordering of order keys.
-            private Dictionary<Wrapper<TInputOutput>, Pair<TInputOutput, TLeftKey>> _hashLookup; // The hash lookup, used to produce the intersection.
+            private Dictionary<Wrapper<TInputOutput>, Pair<TInputOutput, TLeftKey>>? _hashLookup; // The hash lookup, used to produce the intersection.
             private readonly CancellationToken _cancellationToken;
 
             //---------------------------------------------------------------------------------------
@@ -240,7 +242,7 @@ namespace System.Linq.Parallel
             internal OrderedIntersectQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, int> rightSource,
-                IEqualityComparer<TInputOutput> comparer, IComparer<TLeftKey> leftKeyComparer,
+                IEqualityComparer<TInputOutput>? comparer, IComparer<TLeftKey> leftKeyComparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
@@ -257,7 +259,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the intersection.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref TLeftKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref TLeftKey currentKey)
             {
                 Debug.Assert(_leftSource != null);
                 Debug.Assert(_rightSource != null);
@@ -269,7 +271,7 @@ namespace System.Linq.Parallel
                     _hashLookup = new Dictionary<Wrapper<TInputOutput>, Pair<TInputOutput, TLeftKey>>(_comparer);
 
                     Pair<TInputOutput, NoKeyMemoizationRequired> leftElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                    TLeftKey leftKey = default(TLeftKey);
+                    TLeftKey leftKey = default(TLeftKey)!;
                     while (_leftSource.MoveNext(ref leftElement, ref leftKey))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
index 105f930d2dd2324cf52b174b5d5b599a96fb9db8..573ce7e007b53ae5566acb6b16cf5667eb1d81f9 100644 (file)
@@ -45,7 +45,7 @@ namespace System.Linq.Parallel
         private readonly Func<TLeftInput, TKey> _leftKeySelector; // The key selection routine for the outer (left) data source.
         private readonly Func<TRightInput, TKey> _rightKeySelector; // The key selection routine for the inner (right) data source.
         private readonly Func<TLeftInput, TRightInput, TOutput> _resultSelector; // The result selection routine.
-        private readonly IEqualityComparer<TKey> _keyComparer; // An optional key comparison object.
+        private readonly IEqualityComparer<TKey>? _keyComparer; // An optional key comparison object.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new join operator.
@@ -55,7 +55,7 @@ namespace System.Linq.Parallel
                                    Func<TLeftInput, TKey> leftKeySelector,
                                    Func<TRightInput, TKey> rightKeySelector,
                                    Func<TLeftInput, TRightInput, TOutput> resultSelector,
-                                   IEqualityComparer<TKey> keyComparer)
+                                   IEqualityComparer<TKey>? keyComparer)
             : base(left, right)
         {
             Debug.Assert(left != null && right != null, "child data sources cannot be null");
@@ -195,9 +195,9 @@ namespace System.Linq.Parallel
     internal class JoinHashLookupBuilder<TElement, TOrderKey, THashKey> : HashLookupBuilder<TElement, TOrderKey, THashKey>
     {
         private readonly QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> _dataSource; // data source. For building.
-        private readonly IEqualityComparer<THashKey> _keyComparer; // An optional key comparison object.
+        private readonly IEqualityComparer<THashKey>? _keyComparer; // An optional key comparison object.
 
-        internal JoinHashLookupBuilder(QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> dataSource, IEqualityComparer<THashKey> keyComparer)
+        internal JoinHashLookupBuilder(QueryOperatorEnumerator<Pair<TElement, THashKey>, TOrderKey> dataSource, IEqualityComparer<THashKey>? keyComparer)
         {
             Debug.Assert(dataSource != null);
 
index 8bf32ccc289f19060becf73f3dd2de6992521e36..dfd49b306f6e83af176ea772158e638f24d71ecd 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -21,13 +22,13 @@ namespace System.Linq.Parallel
     internal sealed class UnionQueryOperator<TInputOutput> :
         BinaryQueryOperator<TInputOutput, TInputOutput, TInputOutput>
     {
-        private readonly IEqualityComparer<TInputOutput> _comparer; // An equality comparer.
+        private readonly IEqualityComparer<TInputOutput>? _comparer; // An equality comparer.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new union operator.
         //
 
-        internal UnionQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput> comparer)
+        internal UnionQueryOperator(ParallelQuery<TInputOutput> left, ParallelQuery<TInputOutput> right, IEqualityComparer<TInputOutput>? comparer)
             : base(left, right)
         {
             Debug.Assert(left != null && right != null, "child data sources cannot be null");
@@ -182,12 +183,12 @@ namespace System.Linq.Parallel
 
         private class UnionQueryOperatorEnumerator<TLeftKey, TRightKey> : QueryOperatorEnumerator<TInputOutput, int>
         {
-            private QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> _leftSource; // Left data source.
-            private QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TRightKey> _rightSource; // Right data source.
-            private Set<TInputOutput> _hashLookup; // The hash lookup, used to produce the union.
+            private QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey>? _leftSource; // Left data source.
+            private QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TRightKey>? _rightSource; // Right data source.
+            private Set<TInputOutput>? _hashLookup; // The hash lookup, used to produce the union.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount;
-            private readonly IEqualityComparer<TInputOutput> _comparer;
+            private Shared<int>? _outputLoopCount;
+            private readonly IEqualityComparer<TInputOutput>? _comparer;
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new union operator.
@@ -196,7 +197,7 @@ namespace System.Linq.Parallel
             internal UnionQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TRightKey> rightSource,
-                IEqualityComparer<TInputOutput> comparer,
+                IEqualityComparer<TInputOutput>? comparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
@@ -212,7 +213,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the union.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey)
             {
                 if (_hashLookup == null)
                 {
@@ -227,7 +228,7 @@ namespace System.Linq.Parallel
                 if (_leftSource != null)
                 {
                     // Iterate over this set's elements until we find a unique element.
-                    TLeftKey keyUnused = default(TLeftKey);
+                    TLeftKey keyUnused = default(TLeftKey)!;
                     Pair<TInputOutput, NoKeyMemoizationRequired> currentLeftElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
 
                     int i = 0;
@@ -255,11 +256,12 @@ namespace System.Linq.Parallel
                 if (_rightSource != null)
                 {
                     // Iterate over this set's elements until we find a unique element.
-                    TRightKey keyUnused = default(TRightKey);
+                    TRightKey keyUnused = default(TRightKey)!;
                     Pair<TInputOutput, NoKeyMemoizationRequired> currentRightElement = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
 
                     while (_rightSource.MoveNext(ref currentRightElement, ref keyUnused))
                     {
+                        Debug.Assert(_outputLoopCount != null);
                         if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
 
@@ -299,10 +301,10 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> _leftSource; // Left data source.
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TRightKey> _rightSource; // Right data source.
             private readonly IComparer<ConcatKey<TLeftKey, TRightKey>> _keyComparer; // Comparer for compound order keys.
-            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, Pair<TInputOutput, ConcatKey<TLeftKey, TRightKey>>>> _outputEnumerator; // Enumerator over the output of the union.
+            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, Pair<TInputOutput, ConcatKey<TLeftKey, TRightKey>>>>? _outputEnumerator; // Enumerator over the output of the union.
             private readonly bool _leftOrdered; // Whether the left data source is ordered.
             private readonly bool _rightOrdered; // Whether the right data source is ordered.
-            private readonly IEqualityComparer<TInputOutput> _comparer; // Comparer for the elements.
+            private readonly IEqualityComparer<TInputOutput>? _comparer; // Comparer for the elements.
             private readonly CancellationToken _cancellationToken;
 
             //---------------------------------------------------------------------------------------
@@ -312,7 +314,7 @@ namespace System.Linq.Parallel
             internal OrderedUnionQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TLeftKey> leftSource,
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TRightKey> rightSource,
-                bool leftOrdered, bool rightOrdered, IEqualityComparer<TInputOutput> comparer, IComparer<ConcatKey<TLeftKey, TRightKey>> keyComparer,
+                bool leftOrdered, bool rightOrdered, IEqualityComparer<TInputOutput>? comparer, IComparer<ConcatKey<TLeftKey, TRightKey>> keyComparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(leftSource != null);
@@ -338,7 +340,7 @@ namespace System.Linq.Parallel
             // Walks the two data sources, left and then right, to produce the union.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref ConcatKey<TLeftKey, TRightKey> currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref ConcatKey<TLeftKey, TRightKey> currentKey)
             {
                 Debug.Assert(_leftSource != null);
                 Debug.Assert(_rightSource != null);
@@ -350,7 +352,7 @@ namespace System.Linq.Parallel
                         new Dictionary<Wrapper<TInputOutput>, Pair<TInputOutput, ConcatKey<TLeftKey, TRightKey>>>(wrapperComparer);
 
                     Pair<TInputOutput, NoKeyMemoizationRequired> elem = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                    TLeftKey leftKey = default(TLeftKey);
+                    TLeftKey leftKey = default(TLeftKey)!;
 
                     int i = 0;
                     while (_leftSource.MoveNext(ref elem, ref leftKey))
@@ -359,7 +361,7 @@ namespace System.Linq.Parallel
                             CancellationState.ThrowIfCanceled(_cancellationToken);
 
                         ConcatKey<TLeftKey, TRightKey> key =
-                            ConcatKey<TLeftKey, TRightKey>.MakeLeft(_leftOrdered ? leftKey : default(TLeftKey));
+                            ConcatKey<TLeftKey, TRightKey>.MakeLeft(_leftOrdered ? leftKey : default);
                         Pair<TInputOutput, ConcatKey<TLeftKey, TRightKey>> oldEntry;
                         Wrapper<TInputOutput> wrappedElem = new Wrapper<TInputOutput>(elem.First);
 
@@ -369,14 +371,14 @@ namespace System.Linq.Parallel
                         }
                     }
 
-                    TRightKey rightKey = default(TRightKey);
+                    TRightKey rightKey = default(TRightKey)!;
                     while (_rightSource.MoveNext(ref elem, ref rightKey))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
 
                         ConcatKey<TLeftKey, TRightKey> key =
-                            ConcatKey<TLeftKey, TRightKey>.MakeRight(_rightOrdered ? rightKey : default(TRightKey));
+                            ConcatKey<TLeftKey, TRightKey>.MakeRight(_rightOrdered ? rightKey : default);
                         Pair<TInputOutput, ConcatKey<TLeftKey, TRightKey>> oldEntry;
                         Wrapper<TInputOutput> wrappedElem = new Wrapper<TInputOutput>(elem.First);
 
index 2709b5eeed7ab8a860e76116f72fcc4f91452eb2..d88505490f495e97507a51706e4eac2f1254724b 100644 (file)
@@ -86,15 +86,18 @@ namespace System.Linq.Parallel
             QueryResults<TLeftInput> leftChildResults = _leftChild.Open(settings, preferStriping);
             QueryResults<TRightInput> rightChildResults = _rightChild.Open(settings, preferStriping);
 
+            Debug.Assert(settings.DegreeOfParallelism != null);
             int partitionCount = settings.DegreeOfParallelism.Value;
+            Debug.Assert(settings.TaskScheduler != null);
             if (_prematureMergeLeft)
             {
                 PartitionedStreamMerger<TLeftInput> merger = new PartitionedStreamMerger<TLeftInput>(
                     false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, _leftChild.OutputOrdered,
                     settings.CancellationState, settings.QueryId);
                 leftChildResults.GivePartitionedStream(merger);
+                Debug.Assert(merger.MergeExecutor != null);
                 leftChildResults = new ListQueryResults<TLeftInput>(
-                    merger.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
+                    merger.MergeExecutor.GetResultsAsArray()!, partitionCount, preferStriping);
             }
 
             if (_prematureMergeRight)
@@ -103,8 +106,9 @@ namespace System.Linq.Parallel
                     false, ParallelMergeOptions.FullyBuffered, settings.TaskScheduler, _rightChild.OutputOrdered,
                     settings.CancellationState, settings.QueryId);
                 rightChildResults.GivePartitionedStream(merger);
+                Debug.Assert(merger.MergeExecutor != null);
                 rightChildResults = new ListQueryResults<TRightInput>(
-                    merger.MergeExecutor.GetResultsAsArray(), partitionCount, preferStriping);
+                    merger.MergeExecutor.GetResultsAsArray()!, partitionCount, preferStriping);
             }
 
             return new ZipQueryOperatorResults(leftChildResults, rightChildResults, _resultSelector, partitionCount, preferStriping);
index 0ee6c8e90ec944b604cf11968682c380062578ef..9e7ae7f1d0ea6e7ab91e5bdb93c921fe8294d33c 100644 (file)
@@ -104,9 +104,11 @@ namespace System.Linq.Parallel
             internal override void GivePartitionedStream(IPartitionedStreamRecipient<TOutput> recipient)
             {
                 Debug.Assert(IsIndexible == (_op.OrdinalIndexState == OrdinalIndexState.Indexable));
+                Debug.Assert(_settings.ExecutionMode != null);
 
                 if (_settings.ExecutionMode.Value == ParallelExecutionMode.Default && _op.LimitsParallelism)
                 {
+                    Debug.Assert(_settings.DegreeOfParallelism != null);
                     // We need to run the query sequentially up to and including this operator
                     IEnumerable<TOutput> opSequential = _op.AsSequentialQuery(_settings.CancellationState.ExternalCancellationToken);
                     PartitionedStream<TOutput, int> result = ExchangeUtilities.PartitionDataSource(
@@ -115,6 +117,7 @@ namespace System.Linq.Parallel
                 }
                 else if (IsIndexible)
                 {
+                    Debug.Assert(_settings.DegreeOfParallelism != null);
                     // The output of this operator is indexable. Pass the partitioned output into the IPartitionedStreamRecipient.
                     PartitionedStream<TOutput, int> result = ExchangeUtilities.PartitionDataSource(this, _settings.DegreeOfParallelism.Value, _preferStriping);
                     recipient.Receive<int>(result);
index ec62015cc27bdbdab47a02740a44d57fc1eeb812..2f85003883ce8fda30ae20f39a71ec2c6089e7f8 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -36,7 +37,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override int InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override int InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -63,7 +64,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<int, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new CountAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -97,11 +98,11 @@ namespace System.Linq.Parallel
 
             protected override bool MoveNextCore(ref int currentElement)
             {
-                TSource elementUnused = default(TSource);
-                TKey keyUnused = default(TKey);
+                TSource elementUnused = default(TSource)!;
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<TSource, TKey> source = _source;
-                if (source.MoveNext(ref elementUnused, ref keyUnused))
+                if (source.MoveNext(ref elementUnused!, ref keyUnused))
                 {
                     // We just scroll through the enumerator and keep a running count.
                     int count = 0;
@@ -115,7 +116,7 @@ namespace System.Linq.Parallel
                             count++;
                         }
                     }
-                    while (source.MoveNext(ref elementUnused, ref keyUnused));
+                    while (source.MoveNext(ref elementUnused!, ref keyUnused));
 
                     currentElement = count;
                     return true;
index a6953c4c40ca50cc58a4baf5b62ffba0708d50c2..82f7442761c48e4cb90f1bf43bc4a3d34c364f49 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<decimal, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new DecimalAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -111,7 +111,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<decimal, TKey> source = _source;
                 decimal current = default(decimal);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref current, ref keyUnused))
                 {
index 0c3ea472a8834ad191c9ba05257852fd7bc6957b..63abce08ee5b46a1ba467f003fedd8931d34ccbc 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -89,7 +89,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<decimal, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new DecimalMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -126,7 +126,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<decimal, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index bc154662fa46462ed3cb63bc8dc91e48b3a1811d..b88c4353b7f747b17f685a6690492407cc6e9ae5 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<decimal, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new DecimalSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -93,7 +93,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref decimal currentElement)
             {
                 decimal element = default(decimal);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<decimal, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index 526b92a6ed4426a2cc482a778e967b764f6539ec..858e9ac6d1b6150dac155f1d9d171bd1b4c53b63 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<double, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<double, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new DoubleAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -112,7 +112,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<double, TKey> source = _source;
                 double current = default(double);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref current, ref keyUnused))
                 {
index 41f7a5e18b89fe7e670509933f06e3c968bd74bd..e8a647ecf5f3ed568d4b97920bfd0530d8af5725 100644 (file)
@@ -45,7 +45,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -95,7 +95,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<double, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new DoubleMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
@@ -133,7 +133,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<double, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index caf2d4ae26da206164a092c97acf02979ebd68a5..407a957c9d3aa74665b83b24bed58549916af2d3 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<double, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new DoubleSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -93,7 +93,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref double currentElement)
             {
                 double element = default(double);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<double, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index 9711e70c2f6db2f77c82fa25859a44c9ec747f10..e3391c7629030dcb48d98edd168668b2b7c1ff0a 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<double, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<float, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new FloatAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -112,7 +112,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<float, TKey> source = _source;
                 float current = default(float);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref current, ref keyUnused))
                 {
index 5e93b29ebf40f359dc38dbafec3c0161b0df4a69..c082f877fdd495e14cc272f240a428100c2d12e6 100644 (file)
@@ -44,7 +44,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -94,7 +94,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<float, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<float, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new FloatMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -131,7 +131,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<float, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 94b8e788a834dba5cdd7a5ab3f38b0f553a32fe3..fe06bfe74a4c06800f6b62282c822c843e6c0945 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<float, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new FloatSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -94,7 +94,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref double currentElement)
             {
                 float element = default(float);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<float, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index b50c49783032caa33c702897aa821db0fb9236d1..6cf0989cf11de7bbbfe8a59271256541cee04b62 100644 (file)
@@ -49,7 +49,7 @@ namespace System.Linq.Parallel
         internal TResult Aggregate()
         {
             TResult tr;
-            Exception toThrow = null;
+            Exception? toThrow = null;
 
             try
             {
@@ -76,8 +76,7 @@ namespace System.Linq.Parallel
                     // -  We find the external CancellationToken for this query in the OperationCanceledException
                     // -  The externalToken is actually in the canceled state.
 
-                    OperationCanceledException cancelEx = ex as OperationCanceledException;
-                    if (cancelEx != null
+                    if (ex is OperationCanceledException cancelEx
                         && cancelEx.CancellationToken == SpecifiedQuerySettings.CancellationState.ExternalCancellationToken
                         && SpecifiedQuerySettings.CancellationState.ExternalCancellationToken.IsCancellationRequested)
                     {
@@ -111,7 +110,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected abstract TResult InternalAggregate(ref Exception singularExceptionToThrow);
+        protected abstract TResult InternalAggregate(ref Exception? singularExceptionToThrow);
 
         //---------------------------------------------------------------------------------------
         // Just opens the current operator, including opening the child and wrapping it with
@@ -141,7 +140,7 @@ namespace System.Linq.Parallel
         }
 
         protected abstract QueryOperatorEnumerator<TIntermediate, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object sharedData, CancellationToken cancellationToken);
+            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object? sharedData, CancellationToken cancellationToken);
 
         [ExcludeFromCodeCoverage]
         internal override IEnumerable<TIntermediate> AsSequentialQuery(CancellationToken token)
index d4a55e4fc70f6b49685b97c156581dfd33153100..0a163cf51e11e7d97560d3f097e599391721fabd 100644 (file)
@@ -8,6 +8,7 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -51,7 +52,7 @@ namespace System.Linq.Parallel
         // and then one that is used for extensibility by subclasses.
         //
 
-        internal sealed override bool MoveNext(ref TIntermediate currentElement, ref int currentKey)
+        internal sealed override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TIntermediate currentElement, ref int currentKey)
         {
             if (!_done && MoveNextCore(ref currentElement))
             {
index 6b8bc2684971860387dd4477893c856920bd7a0e..b42a80bd72de6f6fe8d4cfc086a5d55f73d8f4dd 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<long, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new IntAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -111,7 +111,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<int, TKey> source = _source;
                 int current = default(int);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref current, ref keyUnused))
                 {
index 863788f3ab2dc3094b20c1db0ff97ca674b81e7f..03e7266a773b366d3c186194a55682bc5badbaad 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override int InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override int InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -89,7 +89,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<int, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new IntMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -126,7 +126,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<int, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index f0e2353394f2c3722f77d24e1aebdeae73317fa7..7de18037559fdb9b3825a96b5101eb1738a13dc0 100644 (file)
@@ -36,7 +36,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override int InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override int InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -63,7 +63,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<int, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new IntSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -97,7 +97,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref int currentElement)
             {
                 int element = default(int);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<int, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index d6188659c5767508058f26ec46ebf0ec18f16a96..48b0407d68bedd110f38d35ff6c69e8cf8848bca 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<long, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<long, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new LongAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -111,7 +111,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<long, TKey> source = _source;
                 long current = default(long);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref current, ref keyUnused))
                 {
index 9209fd02692a9e375d15defb551249437975e7f6..80faf2e1c880efd9b1c0c12d76854841d30dc87d 100644 (file)
@@ -36,7 +36,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override long InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override long InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -63,7 +63,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<long, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<TSource, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new LongCountAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -96,8 +96,8 @@ namespace System.Linq.Parallel
 
             protected override bool MoveNextCore(ref long currentElement)
             {
-                TSource elementUnused = default(TSource);
-                TKey keyUnused = default(TKey);
+                TSource elementUnused = default(TSource)!;
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<TSource, TKey> source = _source;
                 if (source.MoveNext(ref elementUnused, ref keyUnused))
index f5cbeacd9e5b738ed61a517da866b7a4d8b17188..ecd6508da6c8fc245f2da56605d21a130aa0a6e7 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override long InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override long InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -89,7 +89,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<long, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<long, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new LongMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
@@ -127,7 +127,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<long, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index eb0f92d57620dc103aaaa64133acb8ec2d41e31c..8cd53ebca693ca50af3a6523141cd7d4c82a6f89 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override long InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override long InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -62,7 +62,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<long, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<long, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new LongSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -96,7 +96,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref long currentElement)
             {
                 long element = default(long);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<long, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index 4fce94e56035b57c9f766d45972459a465497aea..93463e3c79871a32e78e7b1fc5735f2957f4e42f 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -71,7 +71,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<decimal, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDecimalAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -110,7 +110,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<decimal?, TKey> source = _source;
                 decimal? current = default(decimal?);
-                TKey currentKey = default(TKey);
+                TKey currentKey = default(TKey)!;
                 int i = 0;
                 while (source.MoveNext(ref current, ref currentKey))
                 {
index b2f6050058f54b06893ba0d98ac216bbe56e02ae..804273bd930e66243a557eab9494e3f5cd36aa28 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -88,7 +88,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<decimal?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDecimalMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -125,7 +125,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<decimal?, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 7a907aefad30956a971414fef42b9c3163edb532..10eb623acd97b1ba459edab5604a92fbcf8b7e99 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override decimal? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override decimal? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<decimal?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<decimal?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDecimalSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -93,7 +93,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref decimal? currentElement)
             {
                 decimal? element = default(decimal?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<decimal?, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index caba734329aa418b3cbecc69acfa2851308924f8..83a06eeb30755aa8f5a1d565003d768de0370935 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -71,7 +71,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<double, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDoubleAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -110,7 +110,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<double?, TKey> source = _source;
                 double? current = default(double?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
                 int i = 0;
                 while (source.MoveNext(ref current, ref keyUnused))
                 {
index 9229441f9de264a1a56e6c73060e9dc666806392..b1b083bbb410ca3cc7bbd48ba2ec742e0cfac68d 100644 (file)
@@ -45,7 +45,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -96,7 +96,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDoubleMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -133,7 +133,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<double?, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 62ec3095c3aab4c0079db31f744a1b1d53024024..4d8def186193a573d23361b033252c321dc2fdb4 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<double?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableDoubleSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -93,7 +93,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref double? currentElement)
             {
                 double? element = default(double?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<double?, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index 8381b80d278ab9548a59e9a46118f24a60e378b1..28f118b0b82447bf0d9c2f3f3b6fd1448f3c4098 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -71,7 +71,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<double, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableFloatAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -110,7 +110,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<float?, TKey> source = _source;
                 float? current = default(float?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 int i = 0;
                 while (source.MoveNext(ref current, ref keyUnused))
index 602e3a4676b5e071b66df4ab97aa2fec065e31fd..bea710b46fb6774e956955201864428ea348a53b 100644 (file)
@@ -45,7 +45,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -96,7 +96,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<float?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableFloatMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -133,7 +133,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<float?, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 25bb8bca27bc35c22fa8ebc77f2295c6a7901021..514520fe1bc063b3348a12bbf79915de0bbbfbc6 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override float? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override float? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -59,7 +59,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<double?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<float?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableFloatSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -93,7 +93,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref double? currentElement)
             {
                 float? element = default(float?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<float?, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index b238cf8e122456b3c84393eb6b5ad000968555f9..7f56d5be01a1a821c3de5161f6f9b74e414c9259 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -71,7 +71,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<long, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableIntAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -110,7 +110,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<int?, TKey> source = _source;
                 int? current = default(int?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 int i = 0;
                 while (source.MoveNext(ref current, ref keyUnused))
index c0235145aa07cb29f42c2e63fafcf6c3fc9d168f..bcaf970ef226fb4a8f420980b83e985f44597758 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override int? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override int? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -88,7 +88,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<int?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableIntMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
         }
@@ -125,7 +125,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<int?, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 59f07131a13e55ccd7f84a632d599abdd7e87d41..3bba1be50800fc985b7e0f0225604e4548e9a558 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override int? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override int? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -62,7 +62,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<int?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object sharedData, CancellationToken cancellationToken)
+            int index, int count, QueryOperatorEnumerator<int?, TKey> source, object? sharedData, CancellationToken cancellationToken)
         {
             return new NullableIntSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
         }
@@ -96,7 +96,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref int? currentElement)
             {
                 int? element = default(int?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<int?, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index 20303cb7a2952857775eefe4b8578b672226741d..ad70cd9419f6829d1c4d5c9233a24911bc080512 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override double? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override double? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -71,7 +71,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<Pair<long, long>, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new NullableLongAverageAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -111,7 +111,7 @@ namespace System.Linq.Parallel
 
                 QueryOperatorEnumerator<long?, TKey> source = _source;
                 long? current = default(long?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 int i = 0;
                 while (source.MoveNext(ref current, ref keyUnused))
index ab335e73dff8f6ae17e94ce2978cd27692e10b82..d0575dbe310b224f06506efa54dd757426b69ceb 100644 (file)
@@ -39,7 +39,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override long? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override long? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -88,7 +88,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<long?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new NullableLongMinMaxAggregationOperatorEnumerator<TKey>(source, index, _sign, cancellationToken);
@@ -126,7 +126,7 @@ namespace System.Linq.Parallel
             {
                 // Based on the sign, do either a min or max reduction.
                 QueryOperatorEnumerator<long?, TKey> source = _source;
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 if (source.MoveNext(ref currentElement, ref keyUnused))
                 {
index 91a9d674f0df5565776ceb16ea50f087566b94ab..d6b385477330c3dcb55f979286f8bc2924327262 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     The single result of aggregation.
         //
 
-        protected override long? InternalAggregate(ref Exception singularExceptionToThrow)
+        protected override long? InternalAggregate(ref Exception? singularExceptionToThrow)
         {
             // Because the final reduction is typically much cheaper than the intermediate
             // reductions over the individual partitions, and because each parallel partition
@@ -62,7 +62,7 @@ namespace System.Linq.Parallel
         //
 
         protected override QueryOperatorEnumerator<long?, int> CreateEnumerator<TKey>(
-            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object sharedData,
+            int index, int count, QueryOperatorEnumerator<long?, TKey> source, object? sharedData,
             CancellationToken cancellationToken)
         {
             return new NullableLongSumAggregationOperatorEnumerator<TKey>(source, index, cancellationToken);
@@ -97,7 +97,7 @@ namespace System.Linq.Parallel
             protected override bool MoveNextCore(ref long? currentElement)
             {
                 long? element = default(long?);
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default(TKey)!;
 
                 QueryOperatorEnumerator<long?, TKey> source = _source;
                 if (source.MoveNext(ref element, ref keyUnused))
index de777befa5205c07f769fc9aa086b20034c0e7a4..d50b2b823e782e047dbe8002f31c501f449f0e64 100644 (file)
@@ -37,8 +37,7 @@ namespace System.Linq.Parallel
 
         internal override IEnumerator<TSource> GetEnumerator(ParallelMergeOptions? mergeOptions, bool suppressOrderPreservation)
         {
-            ScanQueryOperator<TSource> childAsScan = _child as ScanQueryOperator<TSource>;
-            if (childAsScan != null)
+            if (_child is ScanQueryOperator<TSource> childAsScan)
             {
                 return childAsScan.Data.GetEnumerator();
             }
index 983a6022e1a04d51267898c06e89d8b5bd734055..6062fd3012f75d61116e303b24558ed9230a351d 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Linq.Parallel
         private readonly bool _forEffectMerge;
         private readonly ParallelMergeOptions _mergeOptions;
         private readonly bool _isOrdered;
-        private MergeExecutor<TOutput> _mergeExecutor = null;
+        private MergeExecutor<TOutput>? _mergeExecutor = null;
         private readonly TaskScheduler _taskScheduler;
         private readonly int _queryId; // ID of the current query execution
 
@@ -31,7 +31,7 @@ namespace System.Linq.Parallel
         private bool _received = false;
 #endif
         // Returns the merge executor which merges the received partitioned stream.
-        internal MergeExecutor<TOutput> MergeExecutor
+        internal MergeExecutor<TOutput>? MergeExecutor
         {
             get
             {
index 197ce737ff0e646c07dd5e25e7652f50f597d3b2..d93f0b74fa90379c66350efc72d0db9401edc292 100644 (file)
@@ -16,6 +16,7 @@ using System.Collections.Concurrent;
 using System.Linq.Parallel;
 using System.Diagnostics;
 using System.Threading;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -74,7 +75,7 @@ namespace System.Linq.Parallel
         /// </summary>
         internal static OrdinalIndexState GetOrdinalIndexState(Partitioner<TElement> partitioner)
         {
-            OrderablePartitioner<TElement> orderablePartitioner = partitioner as OrderablePartitioner<TElement>;
+            OrderablePartitioner<TElement>? orderablePartitioner = partitioner as OrderablePartitioner<TElement>;
 
             if (orderablePartitioner == null)
             {
@@ -130,7 +131,7 @@ namespace System.Linq.Parallel
                 Debug.Assert(_settings.DegreeOfParallelism.HasValue);
                 int partitionCount = _settings.DegreeOfParallelism.Value;
 
-                OrderablePartitioner<TElement> orderablePartitioner = _partitioner as OrderablePartitioner<TElement>;
+                OrderablePartitioner<TElement>? orderablePartitioner = _partitioner as OrderablePartitioner<TElement>;
 
                 // If the partitioner is not orderable, it will yield zeros as order keys. The order index state
                 // is irrelevant.
@@ -213,7 +214,7 @@ namespace System.Linq.Parallel
                 _sourceEnumerator = sourceEnumerator;
             }
 
-            internal override bool MoveNext(ref TElement currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TElement currentElement, ref int currentKey)
             {
                 if (!_sourceEnumerator.MoveNext()) return false;
 
@@ -248,7 +249,7 @@ namespace System.Linq.Parallel
                 _sourceEnumerator = sourceEnumerator;
             }
 
-            internal override bool MoveNext(ref TElement currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TElement currentElement, ref int currentKey)
             {
                 if (!_sourceEnumerator.MoveNext()) return false;
 
index b36fb9c115fae6dd48ba5f44ff8e94f3412b70ef..d7725daf97514622f7132aee839d43833468a815 100644 (file)
@@ -24,7 +24,7 @@ namespace System.Linq.Parallel
     internal class QueryOpeningEnumerator<TOutput> : IEnumerator<TOutput>
     {
         private readonly QueryOperator<TOutput> _queryOperator;
-        private IEnumerator<TOutput> _openedQueryEnumerator;
+        private IEnumerator<TOutput>? _openedQueryEnumerator;
         private QuerySettings _querySettings;
         private readonly ParallelMergeOptions? _mergeOptions;
         private readonly bool _suppressOrderPreservation;
@@ -81,7 +81,7 @@ namespace System.Linq.Parallel
             QueryLifecycle.LogicalQueryExecutionEnd(_querySettings.QueryId);
         }
 
-        object IEnumerator.Current
+        object? IEnumerator.Current
         {
             get { return ((IEnumerator<TOutput>)this).Current; }
         }
@@ -108,7 +108,7 @@ namespace System.Linq.Parallel
                 OpenQuery();
             }
 
-            bool innerMoveNextResult = _openedQueryEnumerator.MoveNext();
+            bool innerMoveNextResult = _openedQueryEnumerator!.MoveNext();
 
             // This provides cancellation-testing for the consumer-side of the buffers that appears in each scenario:
             //   Non-order-preserving (defaultMergeHelper)
index e08c11e49a293dc7b8298ff61b29a944be9a01c9..d7e65e3c28409b947aff38fa05af90f81a84f28d 100644 (file)
@@ -122,9 +122,10 @@ namespace System.Linq.Parallel
         // The enumerator will be "opened", which means that PLINQ will start executing the query
         // immediately, even before the user calls MoveNext() for the first time.
         //
-        internal IEnumerator<TOutput> GetOpenedEnumerator(ParallelMergeOptions? mergeOptions, bool suppressOrder, bool forEffect,
+        internal IEnumerator<TOutput>? GetOpenedEnumerator(ParallelMergeOptions? mergeOptions, bool suppressOrder, bool forEffect,
             QuerySettings querySettings)
         {
+            Debug.Assert(querySettings.ExecutionMode != null);
             // If the top-level enumerator forces a premature merge, run the query sequentially.
             if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
             {
@@ -155,6 +156,7 @@ namespace System.Linq.Parallel
 
             bool orderedMerge = OutputOrdered && !suppressOrder;
 
+            Debug.Assert(querySettings.TaskScheduler != null);
             PartitionedStreamMerger<TOutput> merger = new PartitionedStreamMerger<TOutput>(forEffect, mergeOptions.GetValueOrDefault(),
                                                                                            querySettings.TaskScheduler,
                                                                                            orderedMerge,
@@ -168,6 +170,7 @@ namespace System.Linq.Parallel
                 return null;
             }
 
+            Debug.Assert(merger.MergeExecutor != null);
             return merger.MergeExecutor.GetEnumerator();
         }
 
@@ -201,6 +204,7 @@ namespace System.Linq.Parallel
             QueryLifecycle.LogicalQueryExecutionBegin(querySettings.QueryId);
             try
             {
+                Debug.Assert(querySettings.ExecutionMode != null);
                 if (querySettings.ExecutionMode.Value == ParallelExecutionMode.Default && LimitsParallelism)
                 {
                     IEnumerable<TOutput> opSequential = AsSequentialQuery(querySettings.CancellationState.ExternalCancellationToken);
@@ -235,12 +239,15 @@ namespace System.Linq.Parallel
                 }
                 else
                 {
+                    Debug.Assert(querySettings.TaskScheduler != null);
                     PartitionedStreamMerger<TOutput> merger =
                         new PartitionedStreamMerger<TOutput>(false, ParallelMergeOptions.FullyBuffered, querySettings.TaskScheduler,
                             OutputOrdered, querySettings.CancellationState, querySettings.QueryId);
                     results.GivePartitionedStream(merger);
-                    TOutput[] output = merger.MergeExecutor.GetResultsAsArray();
+                    Debug.Assert(merger.MergeExecutor != null);
+                    TOutput[]? output = merger.MergeExecutor.GetResultsAsArray();
                     querySettings.CleanStateAtQueryEnd();
+                    Debug.Assert(output != null);
                     return output;
                 }
             }
@@ -285,14 +292,13 @@ namespace System.Linq.Parallel
             bool useStriping,
             QuerySettings settings)
         {
-            TaskScheduler taskScheduler = settings.TaskScheduler;
-
-
+            TaskScheduler? taskScheduler = settings.TaskScheduler;
+            Debug.Assert(taskScheduler != null);
 
             MergeExecutor<TOutput> executor = MergeExecutor<TOutput>.Execute<TKey>(
                 openedChild, false, ParallelMergeOptions.FullyBuffered, taskScheduler, outputOrdered,
                 settings.CancellationState, settings.QueryId);
-            return new ListQueryResults<TOutput>(executor.GetResultsAsArray(), partitionCount, useStriping);
+            return new ListQueryResults<TOutput>(executor.GetResultsAsArray()!, partitionCount, useStriping);
         }
 
 
@@ -314,12 +320,11 @@ namespace System.Linq.Parallel
 
             // Just try casting the data source to a query operator, in the case that
             // our child is just another query operator.
-            QueryOperator<TOutput> sourceAsOperator = source as QueryOperator<TOutput>;
+            QueryOperator<TOutput>? sourceAsOperator = source as QueryOperator<TOutput>;
 
             if (sourceAsOperator == null)
             {
-                OrderedParallelQuery<TOutput> orderedQuery = source as OrderedParallelQuery<TOutput>;
-                if (orderedQuery != null)
+                if (source is OrderedParallelQuery<TOutput>  orderedQuery)
                 {
                     // We have to handle OrderedParallelQuery<T> specially. In all other cases,
                     // ParallelQuery *is* the QueryOperator<T>. But, OrderedParallelQuery<T>
index 3e417e41cf1fab9ba8a4af5cefb1a3c5aec79c86..01c5b5806f932549515eadc73e0fcfcc6d83288f 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -23,7 +24,7 @@ namespace System.Linq.Parallel
     {
         // Moves the position of the enumerator forward by one, and simultaneously returns
         // the (new) current element and key. If empty, false is returned.
-        internal abstract bool MoveNext(ref TElement currentElement, ref TKey currentKey);
+        internal abstract bool MoveNext([MaybeNullWhen(false), AllowNull] ref TElement currentElement, ref TKey currentKey);
 
         // Standard implementation of the disposable pattern.
         public void Dispose()
@@ -53,7 +54,7 @@ namespace System.Linq.Parallel
         private class QueryOperatorClassicEnumerator : IEnumerator<TElement>
         {
             private QueryOperatorEnumerator<TElement, TKey> _operatorEnumerator;
-            private TElement _current;
+            private TElement _current = default!;
 
             internal QueryOperatorClassicEnumerator(QueryOperatorEnumerator<TElement, TKey> operatorEnumerator)
             {
@@ -63,8 +64,8 @@ namespace System.Linq.Parallel
 
             public bool MoveNext()
             {
-                TKey keyUnused = default(TKey);
-                return _operatorEnumerator.MoveNext(ref _current, ref keyUnused);
+                TKey keyUnused = default(TKey)!;
+                return _operatorEnumerator.MoveNext(ref _current!, ref keyUnused);
             }
 
             public TElement Current
@@ -72,7 +73,7 @@ namespace System.Linq.Parallel
                 get { return _current; }
             }
 
-            object IEnumerator.Current
+            object? IEnumerator.Current
             {
                 get { return _current; }
             }
@@ -80,7 +81,7 @@ namespace System.Linq.Parallel
             public void Dispose()
             {
                 _operatorEnumerator.Dispose();
-                _operatorEnumerator = null;
+                _operatorEnumerator = null!;
             }
 
             public void Reset()
index 2f305515385b8d6db55b65492c34b6c48ca98120..d9c63bd4e78e262290622b5a2cd67a7e5679a81b 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     /// </summary>
     internal struct QuerySettings
     {
-        private TaskScheduler _taskScheduler;
+        private TaskScheduler? _taskScheduler;
         private int? _degreeOfParallelism;
         private CancellationState _cancellationState;
         private ParallelExecutionMode? _executionMode;
@@ -43,7 +43,7 @@ namespace System.Linq.Parallel
         }
 
         // The task manager on which to execute the query.
-        internal TaskScheduler TaskScheduler
+        internal TaskScheduler? TaskScheduler
         {
             get { return _taskScheduler; }
             set { _taskScheduler = value; }
@@ -80,7 +80,7 @@ namespace System.Linq.Parallel
         //-----------------------------------------------------------------------------------
         // Constructs a new settings structure.
         //
-        internal QuerySettings(TaskScheduler taskScheduler, int? degreeOfParallelism,
+        internal QuerySettings(TaskScheduler? taskScheduler, int? degreeOfParallelism,
             CancellationToken externalCancellationToken, ParallelExecutionMode? executionMode,
             ParallelMergeOptions? mergeOptions)
         {
@@ -124,7 +124,7 @@ namespace System.Linq.Parallel
                 throw new InvalidOperationException(SR.ParallelQuery_DuplicateMergeOptions);
             }
 
-            TaskScheduler tm = (this.TaskScheduler == null) ? settings2.TaskScheduler : this.TaskScheduler;
+            TaskScheduler? tm = (this.TaskScheduler == null) ? settings2.TaskScheduler : this.TaskScheduler;
             int? dop = this.DegreeOfParallelism.HasValue ? this.DegreeOfParallelism : settings2.DegreeOfParallelism;
             CancellationToken externalCancellationToken = (this.CancellationState.ExternalCancellationToken.CanBeCanceled) ? this.CancellationState.ExternalCancellationToken : settings2.CancellationState.ExternalCancellationToken;
             ParallelExecutionMode? executionMode = this.ExecutionMode.HasValue ? this.ExecutionMode : settings2.ExecutionMode;
@@ -220,6 +220,7 @@ namespace System.Linq.Parallel
         // uninterrupted for the duration of the full query.)
         public void CleanStateAtQueryEnd()
         {
+            Debug.Assert(_cancellationState.MergedCancellationTokenSource != null);
             _cancellationState.MergedCancellationTokenSource.Dispose();
         }
     }
index e58e9f8c6e7ed584fc1815a792ae772a3c7ce6af..a063158fa07770e932a8374204c49de0671f472f 100644 (file)
@@ -33,8 +33,7 @@ namespace System.Linq.Parallel
         {
             Debug.Assert(data != null);
 
-            ParallelEnumerableWrapper<TElement> wrapper = data as ParallelEnumerableWrapper<TElement>;
-            if (wrapper != null)
+            if (data is ParallelEnumerableWrapper<TElement> wrapper)
             {
                 data = wrapper.WrappedEnumerable;
             }
@@ -60,8 +59,7 @@ namespace System.Linq.Parallel
         {
             Debug.Assert(settings.DegreeOfParallelism.HasValue);
 
-            IList<TElement> dataAsList = _data as IList<TElement>;
-            if (dataAsList != null)
+            if (_data is IList<TElement> dataAsList)
             {
                 return new ListQueryResults<TElement>(dataAsList, settings.DegreeOfParallelism.GetValueOrDefault(), preferStriping);
             }
@@ -131,6 +129,7 @@ namespace System.Linq.Parallel
 
             internal override void GivePartitionedStream(IPartitionedStreamRecipient<TElement> recipient)
             {
+                Debug.Assert(_settings.DegreeOfParallelism != null);
                 // Since we are not using _data as an IList, we can pass useStriping = false.
                 PartitionedStream<TElement, int> partitionedStream = ExchangeUtilities.PartitionDataSource(
                     _data, _settings.DegreeOfParallelism.Value, false);
index 5b847a67c839153bd235142251fb0d290f0c5a53..e8e86ae50db2729eb46bdb07711765c410fd7bd2 100644 (file)
@@ -191,10 +191,10 @@ namespace System.Linq.Parallel
                     return false;
 
                 // We just scroll through the enumerator and accumulate the result.
-                TInput element = default(TInput);
-                TKey keyUnused = default(TKey);
+                TInput element = default(TInput)!;
+                TKey keyUnused = default(TKey)!;
 
-                if (_source.MoveNext(ref element, ref keyUnused))
+                if (_source.MoveNext(ref element!, ref keyUnused))
                 {
                     currentElement = !_qualification;
                     currentKey = _partitionIndex;
@@ -222,7 +222,7 @@ namespace System.Linq.Parallel
                             break;
                         }
                     }
-                    while (_source.MoveNext(ref element, ref keyUnused));
+                    while (_source.MoveNext(ref element!, ref keyUnused));
 
                     return true;
                 }
index a483c7d9c11c816c20144896653a2bdde15de96e..45be1595f479acd28e3751b7e13fbd21833ee818 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     comparer    - a comparison routine used to test equality.
         //
 
-        internal ContainsSearchOperator(IEnumerable<TInput> child, TInput searchValue, IEqualityComparer<TInput> comparer)
+        internal ContainsSearchOperator(IEnumerable<TInput> child, TInput searchValue, IEqualityComparer<TInput>? comparer)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -177,9 +177,9 @@ namespace System.Linq.Parallel
                     return false;
 
                 // We just scroll through the enumerator and accumulate the result.
-                TInput element = default(TInput);
-                TKey keyUnused = default(TKey);
-                if (_source.MoveNext(ref element, ref keyUnused))
+                TInput element = default(TInput)!;
+                TKey keyUnused = default(TKey)!;
+                if (_source.MoveNext(ref element!, ref keyUnused))
                 {
                     currentElement = false;
                     currentKey = _partitionIndex;
@@ -207,7 +207,7 @@ namespace System.Linq.Parallel
                             break;
                         }
                     }
-                    while (_source.MoveNext(ref element, ref keyUnused));
+                    while (_source.MoveNext(ref element!, ref keyUnused));
 
                     return true;
                 }
index fbe1ae0d99efa39856f8fef919717fa615fa2d1a..ffa93aab0e1edb8fd92c812f36454777ead54aca 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -139,11 +140,11 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref TKey currentKey)
             {
                 Debug.Assert(_source != null);
 
-                bool moveNextResult = _source.MoveNext(ref currentElement, ref currentKey);
+                bool moveNextResult = _source.MoveNext(ref currentElement!, ref currentKey);
 
                 // There is special logic the first time this function is called.
                 if (!_lookedForEmpty)
@@ -167,7 +168,7 @@ namespace System.Linq.Parallel
                             {
                                 // No data, we will yield the default value.
                                 currentElement = _defaultValue;
-                                currentKey = default(TKey);
+                                currentKey = default(TKey)!;
                                 return true;
                             }
                             else
index 578bbe527226b34864f4b37ad7bea3ab831f5791..c1f0d92ad15cdc4a32b30c7220c1702bd0d9aaa0 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -22,13 +23,13 @@ namespace System.Linq.Parallel
     /// <typeparam name="TInputOutput"></typeparam>
     internal sealed class DistinctQueryOperator<TInputOutput> : UnaryQueryOperator<TInputOutput, TInputOutput>
     {
-        private readonly IEqualityComparer<TInputOutput> _comparer; // An (optional) equality comparer.
+        private readonly IEqualityComparer<TInputOutput>? _comparer; // An (optional) equality comparer.
 
         //---------------------------------------------------------------------------------------
         // Constructs a new distinction operator.
         //
 
-        internal DistinctQueryOperator(IEnumerable<TInputOutput> source, IEqualityComparer<TInputOutput> comparer)
+        internal DistinctQueryOperator(IEnumerable<TInputOutput> source, IEqualityComparer<TInputOutput>? comparer)
             : base(source)
         {
             Debug.Assert(source != null, "child data source cannot be null");
@@ -121,14 +122,14 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TKey> _source; // The data source.
             private readonly Set<TInputOutput> _hashLookup; // The hash lookup, used to produce the distinct set.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount; // Allocated in MoveNext to avoid false sharing.
+            private Shared<int>? _outputLoopCount; // Allocated in MoveNext to avoid false sharing.
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new distinction operator.
             //
 
             internal DistinctQueryOperatorEnumerator(
-                QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TKey> source, IEqualityComparer<TInputOutput> comparer,
+                QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TKey> source, IEqualityComparer<TInputOutput>? comparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(source != null);
@@ -141,13 +142,13 @@ namespace System.Linq.Parallel
             // Walks the single data source, skipping elements it has already seen.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey)
             {
                 Debug.Assert(_source != null);
                 Debug.Assert(_hashLookup != null);
 
                 // Iterate over this set's elements until we find a unique element.
-                TKey keyUnused = default(TKey);
+                TKey keyUnused = default!;
                 Pair<TInputOutput, NoKeyMemoizationRequired> current = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
 
                 if (_outputLoopCount == null)
@@ -194,7 +195,7 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TKey> _source; // The data source.
             private readonly Dictionary<Wrapper<TInputOutput>, TKey> _hashLookup; // The hash lookup, used to produce the distinct set.
             private readonly IComparer<TKey> _keyComparer; // Comparer to decide the key order.
-            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, TKey>> _hashLookupEnumerator; // Enumerates over _hashLookup.
+            private IEnumerator<KeyValuePair<Wrapper<TInputOutput>, TKey>>? _hashLookupEnumerator; // Enumerates over _hashLookup.
             private readonly CancellationToken _cancellationToken;
 
             //---------------------------------------------------------------------------------------
@@ -203,7 +204,7 @@ namespace System.Linq.Parallel
 
             internal OrderedDistinctQueryOperatorEnumerator(
                 QueryOperatorEnumerator<Pair<TInputOutput, NoKeyMemoizationRequired>, TKey> source,
-                IEqualityComparer<TInputOutput> comparer, IComparer<TKey> keyComparer,
+                IEqualityComparer<TInputOutput>? comparer, IComparer<TKey> keyComparer,
                 CancellationToken cancellationToken)
             {
                 Debug.Assert(source != null);
@@ -220,7 +221,7 @@ namespace System.Linq.Parallel
             // Walks the single data source, skipping elements it has already seen.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref TKey currentKey)
             {
                 Debug.Assert(_source != null);
                 Debug.Assert(_hashLookup != null);
@@ -228,7 +229,7 @@ namespace System.Linq.Parallel
                 if (_hashLookupEnumerator == null)
                 {
                     Pair<TInputOutput, NoKeyMemoizationRequired> elem = default(Pair<TInputOutput, NoKeyMemoizationRequired>);
-                    TKey orderKey = default(TKey);
+                    TKey orderKey = default!;
 
                     int i = 0;
                     while (_source.MoveNext(ref elem, ref orderKey))
@@ -243,7 +244,7 @@ namespace System.Linq.Parallel
 
                         // If this is the first occurrence of this element, or the order key is lower than all keys we saw previously,
                         // update the order key for this element.
-                        if (!_hashLookup.TryGetValue(wrappedElem, out oldEntry) || _keyComparer.Compare(orderKey, oldEntry) < 0)
+                        if (!_hashLookup.TryGetValue(wrappedElem, out oldEntry!) || _keyComparer.Compare(orderKey, oldEntry) < 0)
                         {
                             // For each "elem" value, we store the smallest key, and the element value that had that key.
                             // Note that even though two element values are "equal" according to the EqualityComparer,
index 7a4ab728446956c27ad1cde68ec20b92acd588f5..e3711bb73764e07fe911485c21d1f5a537b864d2 100644 (file)
@@ -123,18 +123,18 @@ namespace System.Linq.Parallel
         /// <param name="result">result</param>
         /// <param name="withDefaultValue">withDefaultValue</param>
         /// <returns>whether an element with this index exists</returns>
-        internal bool Aggregate(out TSource result, bool withDefaultValue)
+        internal bool Aggregate([MaybeNullWhen(false)] out TSource result, bool withDefaultValue)
         {
             // If we were to insert a premature merge before this ElementAt, and we are executing in conservative mode, run the whole query
             // sequentially.
-            if (LimitsParallelism && SpecifiedQuerySettings.WithDefaults().ExecutionMode.Value != ParallelExecutionMode.ForceParallelism)
+            if (LimitsParallelism && SpecifiedQuerySettings.WithDefaults().ExecutionMode!.Value != ParallelExecutionMode.ForceParallelism)
             {
                 CancellationState cancelState = SpecifiedQuerySettings.CancellationState;
                 if (withDefaultValue)
                 {
                     IEnumerable<TSource> childAsSequential = Child.AsSequentialQuery(cancelState.ExternalCancellationToken);
                     IEnumerable<TSource> childWithCancelChecks = CancellableEnumerable.Wrap(childAsSequential, cancelState.ExternalCancellationToken);
-                    result = ExceptionAggregator.WrapEnumerable(childWithCancelChecks, cancelState).ElementAtOrDefault(_index);
+                    result = ExceptionAggregator.WrapEnumerable(childWithCancelChecks, cancelState).ElementAtOrDefault(_index)!;
                 }
                 else
                 {
@@ -156,7 +156,7 @@ namespace System.Linq.Parallel
                 }
             }
 
-            result = default(TSource);
+            result = default(TSource)!;
             return false;
         }
 
@@ -195,11 +195,11 @@ namespace System.Linq.Parallel
             // partition has signaled that it found the element.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
             {
                 // Just walk the enumerator until we've found the element.
                 int i = 0;
-                while (_source.MoveNext(ref currentElement, ref currentKey))
+                while (_source.MoveNext(ref currentElement!, ref currentKey))
                 {
                     if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
index 3b5caa0749c217187587680318c4a7ca6d80b582..8f01b8defd599ea80d33f00c26ec3234de4bdce4 100644 (file)
@@ -24,7 +24,7 @@ namespace System.Linq.Parallel
     /// <typeparam name="TSource"></typeparam>
     internal sealed class FirstQueryOperator<TSource> : UnaryQueryOperator<TSource, TSource>
     {
-        private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+        private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
         private readonly bool _prematureMergeNeeded; // Whether to prematurely merge the input of this operator.
 
         //---------------------------------------------------------------------------------------
@@ -34,7 +34,7 @@ namespace System.Linq.Parallel
         //     child                - the child whose data we will reverse
         //
 
-        internal FirstQueryOperator(IEnumerable<TSource> child, Func<TSource, bool> predicate)
+        internal FirstQueryOperator(IEnumerable<TSource> child, Func<TSource, bool>? predicate)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -120,7 +120,7 @@ namespace System.Linq.Parallel
         private class FirstQueryOperatorEnumerator<TKey> : QueryOperatorEnumerator<TSource, int>
         {
             private readonly QueryOperatorEnumerator<TSource, TKey> _source; // The data source to enumerate.
-            private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+            private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
             private bool _alreadySearched; // Set once the enumerator has performed the search.
             private readonly int _partitionId; // ID of this partition
 
@@ -135,7 +135,7 @@ namespace System.Linq.Parallel
             //
 
             internal FirstQueryOperatorEnumerator(
-                QueryOperatorEnumerator<TSource, TKey> source, Func<TSource, bool> predicate,
+                QueryOperatorEnumerator<TSource, TKey> source, Func<TSource, bool>? predicate,
                 FirstQueryOperatorState<TKey> operatorState, CountdownEvent sharedBarrier, CancellationToken cancellationToken,
                 IComparer<TKey> keyComparer, int partitionId)
             {
@@ -157,7 +157,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
             {
                 Debug.Assert(_source != null);
 
@@ -167,14 +167,14 @@ namespace System.Linq.Parallel
                 }
 
                 // Look for the lowest element.
-                TSource candidate = default(TSource);
-                TKey candidateKey = default(TKey);
+                TSource candidate = default(TSource)!;
+                TKey candidateKey = default(TKey)!;
                 try
                 {
-                    TSource value = default(TSource);
-                    TKey key = default(TKey);
+                    TSource value = default(TSource)!;
+                    TKey key = default(TKey)!;
                     int i = 0;
-                    while (_source.MoveNext(ref value, ref key))
+                    while (_source.MoveNext(ref value!, ref key))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -234,7 +234,7 @@ namespace System.Linq.Parallel
 
         private class FirstQueryOperatorState<TKey>
         {
-            internal TKey _key;
+            internal TKey _key = default!;
             internal int _partitionId = -1;
         }
     }
index f5dd9ede3536a658adde6a6e3e7ff98041505991..116170fd1d9de1964b121d670e779881b0e32caa 100644 (file)
@@ -60,7 +60,7 @@ namespace System.Linq.Parallel
 
             QueryLifecycle.LogicalQueryExecutionBegin(settingsWithDefaults.QueryId);
 
-            IEnumerator<TInput> enumerator = GetOpenedEnumerator(ParallelMergeOptions.FullyBuffered, true, true,
+            IEnumerator<TInput>? enumerator = GetOpenedEnumerator(ParallelMergeOptions.FullyBuffered, true, true,
                 settingsWithDefaults);
             settingsWithDefaults.CleanStateAtQueryEnd();
             Debug.Assert(enumerator == null);
@@ -147,7 +147,7 @@ namespace System.Linq.Parallel
             // element action for each element.
             //
 
-            internal override bool MoveNext(ref TInput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNull, AllowNull] ref TInput currentElement, ref int currentKey)
             {
                 Debug.Assert(_elementAction != null, "expected a compiled operator");
 
@@ -156,10 +156,10 @@ namespace System.Linq.Parallel
 
                 // Cancellation testing must be performed here as full enumeration occurs within this method.
                 // We only need to throw a simple exception here.. marshalling logic handled via QueryTaskGroupState.QueryEnd (called by ForAllSpoolingTask)
-                TInput element = default(TInput);
-                TKey keyUnused = default(TKey);
+                TInput element = default(TInput)!;
+                TKey keyUnused = default(TKey)!;
                 int i = 0;
-                while (_source.MoveNext(ref element, ref keyUnused))
+                while (_source.MoveNext(ref element!, ref keyUnused))
                 {
                     if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
index 54f3592616a0e9a6f5e8b374d9f2399121b6b925..586c6fa6df381983ba5e36b3ddb8506f4f733ae8 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 using IEnumerator = System.Collections.IEnumerator;
 
@@ -30,8 +31,8 @@ namespace System.Linq.Parallel
         UnaryQueryOperator<TSource, IGrouping<TGroupKey, TElement>>
     {
         private readonly Func<TSource, TGroupKey> _keySelector; // Key selection function.
-        private readonly Func<TSource, TElement> _elementSelector; // Optional element selection function.
-        private readonly IEqualityComparer<TGroupKey> _keyComparer; // An optional key comparison object.
+        private readonly Func<TSource, TElement>? _elementSelector; // Optional element selection function.
+        private readonly IEqualityComparer<TGroupKey>? _keyComparer; // An optional key comparison object.
 
         //---------------------------------------------------------------------------------------
         // Initializes a new group by operator.
@@ -49,8 +50,8 @@ namespace System.Linq.Parallel
 
         internal GroupByQueryOperator(IEnumerable<TSource> child,
                                       Func<TSource, TGroupKey> keySelector,
-                                      Func<TSource, TElement> elementSelector,
-                                      IEqualityComparer<TGroupKey> keyComparer)
+                                      Func<TSource, TElement>? elementSelector,
+                                      IEqualityComparer<TGroupKey>? keyComparer)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -222,13 +223,13 @@ namespace System.Linq.Parallel
         QueryOperatorEnumerator<IGrouping<TGroupKey, TElement>, TOrderKey>
     {
         protected readonly QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> _source; // The data source to enumerate.
-        protected readonly IEqualityComparer<TGroupKey> _keyComparer; // A key comparer.
+        protected readonly IEqualityComparer<TGroupKey>? _keyComparer; // A key comparer.
         protected readonly CancellationToken _cancellationToken;
-        private Mutables _mutables; // All of the mutable state.
+        private Mutables? _mutables; // All of the mutable state.
 
         private class Mutables
         {
-            internal HashLookup<Wrapper<TGroupKey>, ListChunk<TElement>> _hashLookup; // The lookup with key-value mappings.
+            internal HashLookup<Wrapper<TGroupKey>, ListChunk<TElement>>? _hashLookup; // The lookup with key-value mappings.
             internal int _hashLookupIndex; // The current index within the lookup.
         }
 
@@ -238,7 +239,7 @@ namespace System.Linq.Parallel
 
         protected GroupByQueryOperatorEnumerator(
             QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            IEqualityComparer<TGroupKey> keyComparer, CancellationToken cancellationToken)
+            IEqualityComparer<TGroupKey>? keyComparer, CancellationToken cancellationToken)
         {
             Debug.Assert(source != null);
 
@@ -253,22 +254,22 @@ namespace System.Linq.Parallel
         // just enumerate the key-set from the hash-table, retrieving groupings of key-elements.
         //
 
-        internal override bool MoveNext(ref IGrouping<TGroupKey, TElement> currentElement, ref TOrderKey currentKey)
+        internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref IGrouping<TGroupKey, TElement> currentElement, ref TOrderKey currentKey)
         {
             Debug.Assert(_source != null);
 
             // Lazy-init the mutable state. This also means we haven't yet built our lookup of
             // groupings, so we can go ahead and do that too.
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             if (mutables == null)
             {
                 mutables = _mutables = new Mutables();
 
                 // Build the hash lookup and start enumerating the lookup at the beginning.
                 mutables._hashLookup = BuildHashLookup();
-                Debug.Assert(mutables._hashLookup != null);
                 mutables._hashLookupIndex = -1;
             }
+            Debug.Assert(mutables._hashLookup != null);
 
             // Now, with a hash lookup in hand, we just enumerate the keys. So long
             // as the key-value lookup has elements, we have elements.
@@ -308,7 +309,7 @@ namespace System.Linq.Parallel
 
         internal GroupByIdentityQueryOperatorEnumerator(
             QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            IEqualityComparer<TGroupKey> keyComparer, CancellationToken cancellationToken)
+            IEqualityComparer<TGroupKey>? keyComparer, CancellationToken cancellationToken)
             : base(source, keyComparer, cancellationToken)
         {
         }
@@ -323,7 +324,7 @@ namespace System.Linq.Parallel
                 new HashLookup<Wrapper<TGroupKey>, ListChunk<TSource>>(new WrapperEqualityComparer<TGroupKey>(_keyComparer));
 
             Pair<TSource, TGroupKey> sourceElement = default(Pair<TSource, TGroupKey>);
-            TOrderKey sourceKeyUnused = default(TOrderKey);
+            TOrderKey sourceKeyUnused = default(TOrderKey)!;
             int i = 0;
             while (_source.MoveNext(ref sourceElement, ref sourceKeyUnused))
             {
@@ -335,7 +336,7 @@ namespace System.Linq.Parallel
 
                 // If the key already exists, we just append it to the existing list --
                 // otherwise we will create a new one and add it to that instead.
-                ListChunk<TSource> currentValue = null;
+                ListChunk<TSource>? currentValue = null;
                 if (!hashlookup.TryGetValue(key, ref currentValue))
                 {
                     const int INITIAL_CHUNK_SIZE = 2;
@@ -368,7 +369,7 @@ namespace System.Linq.Parallel
 
         internal GroupByElementSelectorQueryOperatorEnumerator(
             QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            IEqualityComparer<TGroupKey> keyComparer, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken) :
+            IEqualityComparer<TGroupKey>? keyComparer, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken) :
             base(source, keyComparer, cancellationToken)
         {
             Debug.Assert(elementSelector != null);
@@ -385,7 +386,7 @@ namespace System.Linq.Parallel
                 new HashLookup<Wrapper<TGroupKey>, ListChunk<TElement>>(new WrapperEqualityComparer<TGroupKey>(_keyComparer));
 
             Pair<TSource, TGroupKey> sourceElement = default(Pair<TSource, TGroupKey>);
-            TOrderKey sourceKeyUnused = default(TOrderKey);
+            TOrderKey sourceKeyUnused = default(TOrderKey)!;
             int i = 0;
             while (_source.MoveNext(ref sourceElement, ref sourceKeyUnused))
             {
@@ -397,7 +398,7 @@ namespace System.Linq.Parallel
 
                 // If the key already exists, we just append it to the existing list --
                 // otherwise we will create a new one and add it to that instead.
-                ListChunk<TElement> currentValue = null;
+                ListChunk<TElement>? currentValue = null;
                 if (!hashlookup.TryGetValue(key, ref currentValue))
                 {
                     const int INITIAL_CHUNK_SIZE = 2;
@@ -424,14 +425,14 @@ namespace System.Linq.Parallel
     {
         protected readonly QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> _source; // The data source to enumerate.
         private readonly Func<TSource, TGroupKey> _keySelector; // The key selection routine.
-        protected readonly IEqualityComparer<TGroupKey> _keyComparer; // The key comparison routine.
+        protected readonly IEqualityComparer<TGroupKey>? _keyComparer; // The key comparison routine.
         protected readonly IComparer<TOrderKey> _orderComparer; // The comparison routine for order keys.
         protected readonly CancellationToken _cancellationToken;
-        private Mutables _mutables; // All the mutable state.
+        private Mutables? _mutables; // All the mutable state.
 
         private class Mutables
         {
-            internal HashLookup<Wrapper<TGroupKey>, GroupKeyData> _hashLookup; // The lookup with key-value mappings.
+            internal HashLookup<Wrapper<TGroupKey>, GroupKeyData>? _hashLookup; // The lookup with key-value mappings.
             internal int _hashLookupIndex; // The current index within the lookup.
         }
 
@@ -440,7 +441,7 @@ namespace System.Linq.Parallel
         //
 
         protected OrderedGroupByQueryOperatorEnumerator(QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            Func<TSource, TGroupKey> keySelector, IEqualityComparer<TGroupKey> keyComparer, IComparer<TOrderKey> orderComparer,
+            Func<TSource, TGroupKey> keySelector, IEqualityComparer<TGroupKey>? keyComparer, IComparer<TOrderKey> orderComparer,
             CancellationToken cancellationToken)
         {
             Debug.Assert(source != null);
@@ -459,23 +460,23 @@ namespace System.Linq.Parallel
         // just enumerate the key-set from the hash-table, retrieving groupings of key-elements.
         //
 
-        internal override bool MoveNext(ref IGrouping<TGroupKey, TElement> currentElement, ref TOrderKey currentKey)
+        internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref IGrouping<TGroupKey, TElement> currentElement, ref TOrderKey currentKey)
         {
             Debug.Assert(_source != null);
             Debug.Assert(_keySelector != null);
 
             // Lazy-init the mutable state. This also means we haven't yet built our lookup of
             // groupings, so we can go ahead and do that too.
-            Mutables mutables = _mutables;
+            Mutables? mutables = _mutables;
             if (mutables == null)
             {
                 mutables = _mutables = new Mutables();
 
                 // Build the hash lookup and start enumerating the lookup at the beginning.
                 mutables._hashLookup = BuildHashLookup();
-                Debug.Assert(mutables._hashLookup != null);
                 mutables._hashLookupIndex = -1;
             }
+            Debug.Assert(mutables._hashLookup != null);
 
             // Now, with a hash lookup in hand, we just enumerate the keys. So long
             // as the key-value lookup has elements, we have elements.
@@ -536,7 +537,7 @@ namespace System.Linq.Parallel
         //
 
         internal OrderedGroupByIdentityQueryOperatorEnumerator(QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            Func<TSource, TGroupKey> keySelector, IEqualityComparer<TGroupKey> keyComparer, IComparer<TOrderKey> orderComparer,
+            Func<TSource, TGroupKey> keySelector, IEqualityComparer<TGroupKey>? keyComparer, IComparer<TOrderKey> orderComparer,
             CancellationToken cancellationToken)
             : base(source, keySelector, keyComparer, orderComparer, cancellationToken)
         {
@@ -552,7 +553,7 @@ namespace System.Linq.Parallel
                 new WrapperEqualityComparer<TGroupKey>(_keyComparer));
 
             Pair<TSource, TGroupKey> sourceElement = default(Pair<TSource, TGroupKey>);
-            TOrderKey sourceOrderKey = default(TOrderKey);
+            TOrderKey sourceOrderKey = default(TOrderKey)!;
             int i = 0;
             while (_source.MoveNext(ref sourceElement, ref sourceOrderKey))
             {
@@ -564,7 +565,7 @@ namespace System.Linq.Parallel
 
                 // If the key already exists, we just append it to the existing list --
                 // otherwise we will create a new one and add it to that instead.
-                GroupKeyData currentValue = null;
+                GroupKeyData? currentValue = null;
                 if (hashLookup.TryGetValue(key, ref currentValue))
                 {
                     if (_orderComparer.Compare(sourceOrderKey, currentValue._orderKey) < 0)
@@ -609,7 +610,7 @@ namespace System.Linq.Parallel
         //
 
         internal OrderedGroupByElementSelectorQueryOperatorEnumerator(QueryOperatorEnumerator<Pair<TSource, TGroupKey>, TOrderKey> source,
-            Func<TSource, TGroupKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TGroupKey> keyComparer, IComparer<TOrderKey> orderComparer,
+            Func<TSource, TGroupKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TGroupKey>? keyComparer, IComparer<TOrderKey> orderComparer,
             CancellationToken cancellationToken) :
             base(source, keySelector, keyComparer, orderComparer, cancellationToken)
         {
@@ -627,7 +628,7 @@ namespace System.Linq.Parallel
                 new WrapperEqualityComparer<TGroupKey>(_keyComparer));
 
             Pair<TSource, TGroupKey> sourceElement = default(Pair<TSource, TGroupKey>);
-            TOrderKey sourceOrderKey = default(TOrderKey);
+            TOrderKey sourceOrderKey = default(TOrderKey)!;
             int i = 0;
             while (_source.MoveNext(ref sourceElement, ref sourceOrderKey))
             {
@@ -639,7 +640,7 @@ namespace System.Linq.Parallel
 
                 // If the key already exists, we just append it to the existing list --
                 // otherwise we will create a new one and add it to that instead.
-                GroupKeyData currentValue = null;
+                GroupKeyData? currentValue = null;
                 if (hashLookup.TryGetValue(key, ref currentValue))
                 {
                     if (_orderComparer.Compare(sourceOrderKey, currentValue._orderKey) < 0)
@@ -727,8 +728,8 @@ namespace System.Linq.Parallel
         private const int INITIAL_CHUNK_SIZE = 2;
 
         private readonly TGroupKey _groupKey; // The group key for this grouping
-        private ListChunk<Pair<TOrderKey, TElement>> _values; // Values in this group
-        private TElement[] _sortedValues; // Sorted values (allocated in DoneAdding)
+        private ListChunk<Pair<TOrderKey, TElement>>? _values; // Values in this group
+        private TElement[]? _sortedValues; // Sorted values (allocated in DoneAdding)
         private readonly IComparer<TOrderKey> _orderComparer; // Comparer for order keys
 
         /// <summary>
@@ -784,7 +785,7 @@ namespace System.Linq.Parallel
             Debug.Assert(_values != null);
 
             int count = _values.Count;
-            ListChunk<Pair<TOrderKey, TElement>> curChunk = _values;
+            ListChunk<Pair<TOrderKey, TElement>>? curChunk = _values;
             while ((curChunk = curChunk.Next) != null)
             {
                 count += curChunk.Count;
index 507a8aad13bd8c6d9ccf73887fb01021976a5570..d6b65908cfdbfdc8c71cce7bb160bc51d231b6f1 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -152,11 +153,11 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TOutput currentElement, ref int currentKey)
             {
                 // So long as the source has a next element, we have an element.
-                TInput element = default(TInput);
-                if (_source.MoveNext(ref element, ref currentKey))
+                TInput element = default(TInput)!;
+                if (_source.MoveNext(ref element!, ref currentKey))
                 {
                     Debug.Assert(_selector != null, "expected a compiled selection function");
                     currentElement = _selector(element, currentKey);
index 837b290243e6e5298be4fc2983aff4f648aeaacd..961a63ace94d284d5bcddf972e399976b3fd1c4b 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -141,7 +142,7 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<TInputOutput, int> _source; // The data source to enumerate.
             private readonly Func<TInputOutput, int, bool> _predicate; // The predicate used for filtering.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount;
+            private Shared<int>? _outputLoopCount;
             //-----------------------------------------------------------------------------------
             // Instantiates a new enumerator.
             //
@@ -160,7 +161,7 @@ namespace System.Linq.Parallel
             // Moves to the next matching element in the underlying data stream.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref int currentKey)
             {
                 Debug.Assert(_predicate != null, "expected a compiled operator");
 
@@ -170,7 +171,7 @@ namespace System.Linq.Parallel
                 if (_outputLoopCount == null)
                     _outputLoopCount = new Shared<int>(0);
 
-                while (_source.MoveNext(ref currentElement, ref currentKey))
+                while (_source.MoveNext(ref currentElement!, ref currentKey))
                 {
                     if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
index 8a08d4a8b2c7f44e5a7f4ac77bcc7ba5156eccdd..87d43f159e1c97f782b008b88ce2e7e9fd5dc794 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     /// <typeparam name="TSource"></typeparam>
     internal sealed class LastQueryOperator<TSource> : UnaryQueryOperator<TSource, TSource>
     {
-        private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+        private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
         private readonly bool _prematureMergeNeeded; // Whether to prematurely merge the input of this operator.
 
         //---------------------------------------------------------------------------------------
@@ -35,7 +35,7 @@ namespace System.Linq.Parallel
         //     child                - the child whose data we will reverse
         //
 
-        internal LastQueryOperator(IEnumerable<TSource> child, Func<TSource, bool> predicate)
+        internal LastQueryOperator(IEnumerable<TSource> child, Func<TSource, bool>? predicate)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -116,7 +116,7 @@ namespace System.Linq.Parallel
         private class LastQueryOperatorEnumerator<TKey> : QueryOperatorEnumerator<TSource, int>
         {
             private readonly QueryOperatorEnumerator<TSource, TKey> _source; // The data source to enumerate.
-            private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+            private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
             private bool _alreadySearched; // Set once the enumerator has performed the search.
             private readonly int _partitionId; // ID of this partition
 
@@ -131,7 +131,7 @@ namespace System.Linq.Parallel
             //
 
             internal LastQueryOperatorEnumerator(
-                QueryOperatorEnumerator<TSource, TKey> source, Func<TSource, bool> predicate,
+                QueryOperatorEnumerator<TSource, TKey> source, Func<TSource, bool>? predicate,
                 LastQueryOperatorState<TKey> operatorState, CountdownEvent sharedBarrier, CancellationToken cancelToken,
                 IComparer<TKey> keyComparer, int partitionId)
             {
@@ -153,7 +153,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
             {
                 Debug.Assert(_source != null);
 
@@ -163,15 +163,15 @@ namespace System.Linq.Parallel
                 }
 
                 // Look for the greatest element.
-                TSource candidate = default(TSource);
-                TKey candidateKey = default(TKey);
+                TSource candidate = default(TSource)!;
+                TKey candidateKey = default(TKey)!;
                 bool candidateFound = false;
                 try
                 {
                     int loopCount = 0; //counter to help with cancellation
-                    TSource value = default(TSource);
-                    TKey key = default(TKey);
-                    while (_source.MoveNext(ref value, ref key))
+                    TSource value = default(TSource)!;
+                    TKey key = default(TKey)!;
+                    while (_source.MoveNext(ref value!, ref key))
                     {
                         if ((loopCount & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -237,7 +237,7 @@ namespace System.Linq.Parallel
 
         private class LastQueryOperatorState<TKey>
         {
-            internal TKey _key;
+            internal TKey _key = default!;
             internal int _partitionId = -1;
         }
     }
index efe1e3d057a457d09f918c31b4ec1672fac9cd90..07bb0968d47d1d53da0e552e4c2d07ff29ab5975 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -105,8 +106,8 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<TSource, TKey> _source; // The data source to reverse.
             private readonly CancellationToken _cancellationToken;
-            private List<Pair<TSource, TKey>> _buffer; // Our buffer. [allocate in moveNext to avoid false-sharing]
-            private Shared<int> _bufferIndex; // Our current index within the buffer. [allocate in moveNext to avoid false-sharing]
+            private List<Pair<TSource, TKey>>? _buffer; // Our buffer. [allocate in moveNext to avoid false-sharing]
+            private Shared<int>? _bufferIndex; // Our current index within the buffer. [allocate in moveNext to avoid false-sharing]
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new select enumerator.
@@ -124,7 +125,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref TKey currentKey)
             {
                 // If the buffer has not been created, we will generate it lazily on demand.
                 if (_buffer == null)
@@ -132,10 +133,10 @@ namespace System.Linq.Parallel
                     _bufferIndex = new Shared<int>(0);
                     // Buffer all of our data.
                     _buffer = new List<Pair<TSource, TKey>>();
-                    TSource current = default(TSource);
-                    TKey key = default(TKey);
+                    TSource current = default(TSource)!;
+                    TKey key = default(TKey)!;
                     int i = 0;
-                    while (_source.MoveNext(ref current, ref key))
+                    while (_source.MoveNext(ref current!, ref key))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -144,6 +145,7 @@ namespace System.Linq.Parallel
                         _bufferIndex.Value++;
                     }
                 }
+                Debug.Assert(_bufferIndex != null);
 
                 // Continue yielding elements from our buffer.
                 if (--_bufferIndex.Value >= 0)
index d79d92619788177a34a86522fe7540bae2dd0ddb..51a0e8e416bcdae8f2b96745ace0a14c7039c6c0 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -32,9 +33,9 @@ namespace System.Linq.Parallel
     /// <typeparam name="TOutput"></typeparam>
     internal sealed class SelectManyQueryOperator<TLeftInput, TRightInput, TOutput> : UnaryQueryOperator<TLeftInput, TOutput>
     {
-        private readonly Func<TLeftInput, IEnumerable<TRightInput>> _rightChildSelector; // To select a new child each iteration.
-        private readonly Func<TLeftInput, int, IEnumerable<TRightInput>> _indexedRightChildSelector; // To select a new child each iteration.
-        private readonly Func<TLeftInput, TRightInput, TOutput> _resultSelector; // An optional result selection function.
+        private readonly Func<TLeftInput, IEnumerable<TRightInput>>? _rightChildSelector; // To select a new child each iteration.
+        private readonly Func<TLeftInput, int, IEnumerable<TRightInput>>? _indexedRightChildSelector; // To select a new child each iteration.
+        private readonly Func<TLeftInput, TRightInput, TOutput>? _resultSelector; // An optional result selection function.
         private bool _prematureMerge = false; // Whether to prematurely merge the input of this operator.
         private bool _limitsParallelism = false; // Whether to prematurely merge the input of this operator.
 
@@ -50,9 +51,9 @@ namespace System.Linq.Parallel
         //
 
         internal SelectManyQueryOperator(IEnumerable<TLeftInput> leftChild,
-                                         Func<TLeftInput, IEnumerable<TRightInput>> rightChildSelector,
-                                         Func<TLeftInput, int, IEnumerable<TRightInput>> indexedRightChildSelector,
-                                         Func<TLeftInput, TRightInput, TOutput> resultSelector)
+                                         Func<TLeftInput, IEnumerable<TRightInput>>? rightChildSelector,
+                                         Func<TLeftInput, int, IEnumerable<TRightInput>>? indexedRightChildSelector,
+                                         Func<TLeftInput, TRightInput, TOutput>? resultSelector)
             : base(leftChild)
         {
             Debug.Assert(leftChild != null, "left child data source cannot be null");
@@ -234,15 +235,15 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<TLeftInput, int> _leftSource; // The left data source to enumerate.
             private readonly SelectManyQueryOperator<TLeftInput, TRightInput, TOutput> _selectManyOperator; // The select many operator to use.
-            private IEnumerator<TRightInput> _currentRightSource; // The current enumerator we're using.
-            private IEnumerator<TOutput> _currentRightSourceAsOutput; // If we need to access the enumerator for output directly (no result selector).
-            private Mutables _mutables; // bag of frequently mutated value types [allocate in moveNext to avoid false-sharing]
+            private IEnumerator<TRightInput>? _currentRightSource; // The current enumerator we're using.
+            private IEnumerator<TOutput>? _currentRightSourceAsOutput; // If we need to access the enumerator for output directly (no result selector).
+            private Mutables? _mutables; // bag of frequently mutated value types [allocate in moveNext to avoid false-sharing]
             private readonly CancellationToken _cancellationToken;
 
             private class Mutables
             {
                 internal int _currentRightSourceIndex = -1; // The index for the right data source.
-                internal TLeftInput _currentLeftElement; // The current element in the left data source.
+                internal TLeftInput _currentLeftElement = default!; // The current element in the left data source.
                 internal int _currentLeftSourceIndex; // The current key in the left data source.
                 internal int _lhsCount; //counts the number of lhs elements enumerated. used for cancellation testing.
             }
@@ -270,7 +271,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TOutput currentElement, ref Pair<int, int> currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TOutput currentElement, ref Pair<int, int> currentKey)
             {
                 while (true)
                 {
@@ -286,11 +287,12 @@ namespace System.Linq.Parallel
                         // We don't have a "current" right enumerator to use. We have to fetch the next
                         // one. If the left has run out of elements, however, we're done and just return
                         // false right away.
-                        if (!_leftSource.MoveNext(ref _mutables._currentLeftElement, ref _mutables._currentLeftSourceIndex))
+                        if (!_leftSource.MoveNext(ref _mutables._currentLeftElement!, ref _mutables._currentLeftSourceIndex))
                         {
                             return false;
                         }
 
+                        Debug.Assert(_selectManyOperator._indexedRightChildSelector != null);
                         // Use the source selection routine to create a right child.
                         IEnumerable<TRightInput> rightChild =
                             _selectManyOperator._indexedRightChildSelector(_mutables._currentLeftElement, _mutables._currentLeftSourceIndex);
@@ -316,6 +318,7 @@ namespace System.Linq.Parallel
 
                     if (_currentRightSource.MoveNext())
                     {
+                        Debug.Assert(_mutables != null);
                         _mutables._currentRightSourceIndex++;
 
                         // If the inner data source has an element, we can yield it.
@@ -364,16 +367,16 @@ namespace System.Linq.Parallel
         {
             private readonly QueryOperatorEnumerator<TLeftInput, TLeftKey> _leftSource; // The left data source to enumerate.
             private readonly SelectManyQueryOperator<TLeftInput, TRightInput, TOutput> _selectManyOperator; // The select many operator to use.
-            private IEnumerator<TRightInput> _currentRightSource; // The current enumerator we're using.
-            private IEnumerator<TOutput> _currentRightSourceAsOutput; // If we need to access the enumerator for output directly (no result selector).
-            private Mutables _mutables; // bag of frequently mutated value types [allocate in moveNext to avoid false-sharing]
+            private IEnumerator<TRightInput>? _currentRightSource; // The current enumerator we're using.
+            private IEnumerator<TOutput>? _currentRightSourceAsOutput; // If we need to access the enumerator for output directly (no result selector).
+            private Mutables? _mutables; // bag of frequently mutated value types [allocate in moveNext to avoid false-sharing]
             private readonly CancellationToken _cancellationToken;
 
             private class Mutables
             {
                 internal int _currentRightSourceIndex = -1; // The index for the right data source.
-                internal TLeftInput _currentLeftElement; // The current element in the left data source.
-                internal TLeftKey _currentLeftKey; // The current key in the left data source.
+                internal TLeftInput _currentLeftElement = default!; // The current element in the left data source.
+                internal TLeftKey _currentLeftKey = default!; // The current key in the left data source.
                 internal int _lhsCount; // Counts the number of lhs elements enumerated. used for cancellation testing.
             }
 
@@ -400,7 +403,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TOutput currentElement, ref Pair<TLeftKey, int> currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TOutput currentElement, ref Pair<TLeftKey, int> currentKey)
             {
                 while (true)
                 {
@@ -417,11 +420,12 @@ namespace System.Linq.Parallel
                         // one. If the left has run out of elements, however, we're done and just return
                         // false right away.
 
-                        if (!_leftSource.MoveNext(ref _mutables._currentLeftElement, ref _mutables._currentLeftKey))
+                        if (!_leftSource.MoveNext(ref _mutables._currentLeftElement!, ref _mutables._currentLeftKey))
                         {
                             return false;
                         }
 
+                        Debug.Assert(_selectManyOperator._rightChildSelector != null);
                         // Use the source selection routine to create a right child.
                         IEnumerable<TRightInput> rightChild = _selectManyOperator._rightChildSelector(_mutables._currentLeftElement);
 
@@ -446,6 +450,7 @@ namespace System.Linq.Parallel
 
                     if (_currentRightSource.MoveNext())
                     {
+                        Debug.Assert(_mutables != null);
                         _mutables._currentRightSourceIndex++;
 
                         // If the inner data source has an element, we can yield it.
index 21ee53bdfae00c3b05c9535b9d8191f3fb3e88ff..15722b66fa406f8cf69e83ea816313d2cc980f95 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -111,11 +112,11 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TOutput currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TOutput currentElement, ref TKey currentKey)
             {
                 // So long as the source has a next element, we have an element.
-                TInput element = default(TInput);
-                if (_source.MoveNext(ref element, ref currentKey))
+                TInput element = default(TInput)!;
+                if (_source.MoveNext(ref element!, ref currentKey))
                 {
                     Debug.Assert(_selector != null, "expected a compiled operator");
                     currentElement = _selector(element);
index b25cbe6fbfa3a26e12354a1146ef74629cc22939..519b6e2e2976786f4280a0db995e62f3e65993aa 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     /// <typeparam name="TSource"></typeparam>
     internal sealed class SingleQueryOperator<TSource> : UnaryQueryOperator<TSource, TSource>
     {
-        private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+        private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
 
         //---------------------------------------------------------------------------------------
         // Initializes a new Single operator.
@@ -34,7 +34,7 @@ namespace System.Linq.Parallel
         //     child                - the child whose data we will reverse
         //
 
-        internal SingleQueryOperator(IEnumerable<TSource> child, Func<TSource, bool> predicate)
+        internal SingleQueryOperator(IEnumerable<TSource> child, Func<TSource, bool>? predicate)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -97,7 +97,7 @@ namespace System.Linq.Parallel
         private class SingleQueryOperatorEnumerator<TKey> : QueryOperatorEnumerator<TSource, int>
         {
             private readonly QueryOperatorEnumerator<TSource, TKey> _source; // The data source to enumerate.
-            private readonly Func<TSource, bool> _predicate; // The optional predicate used during the search.
+            private readonly Func<TSource, bool>? _predicate; // The optional predicate used during the search.
             private bool _alreadySearched; // Whether we have searched our input already.
             private bool _yieldExtra; // Whether we found more than one element.
 
@@ -109,7 +109,7 @@ namespace System.Linq.Parallel
             //
 
             internal SingleQueryOperatorEnumerator(QueryOperatorEnumerator<TSource, TKey> source,
-                                                   Func<TSource, bool> predicate, Shared<int> totalElementCount)
+                                                   Func<TSource, bool>? predicate, Shared<int> totalElementCount)
             {
                 Debug.Assert(source != null);
                 Debug.Assert(totalElementCount != null);
@@ -123,7 +123,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TSource currentElement, ref int currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TSource currentElement, ref int currentKey)
             {
                 Debug.Assert(_source != null);
 
@@ -134,7 +134,7 @@ namespace System.Linq.Parallel
                     if (_yieldExtra)
                     {
                         _yieldExtra = false;
-                        currentElement = default(TSource);
+                        currentElement = default(TSource)!;
                         currentKey = 0;
                         return true;
                     }
@@ -144,10 +144,10 @@ namespace System.Linq.Parallel
 
                 // Scan our input, looking for a match.
                 bool found = false;
-                TSource current = default(TSource);
-                TKey keyUnused = default(TKey);
+                TSource current = default(TSource)!;
+                TKey keyUnused = default(TKey)!;
 
-                while (_source.MoveNext(ref current, ref keyUnused))
+                while (_source.MoveNext(ref current!, ref keyUnused))
                 {
                     // If the predicate is null or the current element satisfies it, we will remember
                     // it so that we can yield it later.  We then proceed with scanning the input
index 048c3857489d44d749aeaf15b04b5c0b245e43d6..2dbe161e68ac821f3c3f3366783d0cd9a87e6984 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -30,7 +31,7 @@ namespace System.Linq.Parallel
         //
 
         internal SortQueryOperator(IEnumerable<TInputOutput> source, Func<TInputOutput, TSortKey> keySelector,
-                                   IComparer<TSortKey> comparer, bool descending)
+                                   IComparer<TSortKey>? comparer, bool descending)
             : base(source, true)
         {
             Debug.Assert(keySelector != null, "key selector must not be null");
@@ -60,7 +61,7 @@ namespace System.Linq.Parallel
         //
 
         IOrderedEnumerable<TInputOutput> IOrderedEnumerable<TInputOutput>.CreateOrderedEnumerable<TKey2>(
-            Func<TInputOutput, TKey2> key2Selector, IComparer<TKey2> key2Comparer, bool descending)
+            Func<TInputOutput, TKey2> key2Selector, IComparer<TKey2>? key2Comparer, bool descending)
         {
             key2Comparer = key2Comparer ?? Util.GetDefaultComparer<TKey2>();
 
@@ -175,7 +176,7 @@ namespace System.Linq.Parallel
 
     internal class SortQueryOperatorEnumerator<TInputOutput, TKey, TSortKey> : QueryOperatorEnumerator<TInputOutput, TSortKey>
     {
-        private readonly QueryOperatorEnumerator<TInputOutput, TKey> _source; // Data source to sort.
+        private readonly QueryOperatorEnumerator<TInputOutput, TKey>? _source; // Data source to sort.
         private readonly Func<TInputOutput, TSortKey> _keySelector; // Key selector used when sorting.
 
         //---------------------------------------------------------------------------------------
@@ -198,12 +199,12 @@ namespace System.Linq.Parallel
         // in memory, and the data sorted.
         //
 
-        internal override bool MoveNext(ref TInputOutput currentElement, ref TSortKey currentKey)
+        internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref TSortKey currentKey)
         {
             Debug.Assert(_source != null);
 
-            TKey keyUnused = default(TKey);
-            if (!_source.MoveNext(ref currentElement, ref keyUnused))
+            TKey keyUnused = default(TKey)!;
+            if (!_source.MoveNext(ref currentElement!, ref keyUnused))
             {
                 return false;
             }
index 3242724dba42cbd9e584f5673eb4b0182c4f9e73..f6c80181d5c923ad851e02d97b924bb78774ff63 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -157,8 +158,8 @@ namespace System.Linq.Parallel
             private readonly CountdownEvent _sharedBarrier; // To separate the search/yield phases.
             private readonly CancellationToken _cancellationToken; // Indicates that cancellation has occurred.
 
-            private List<Pair<TResult, TKey>> _buffer; // Our buffer.
-            private Shared<int> _bufferIndex; // Our current index within the buffer. [allocate in moveNext to avoid false-sharing]
+            private List<Pair<TResult, TKey>>? _buffer; // Our buffer.
+            private Shared<int>? _bufferIndex; // Our current index within the buffer. [allocate in moveNext to avoid false-sharing]
 
             //---------------------------------------------------------------------------------------
             // Instantiates a new select enumerator.
@@ -187,7 +188,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TResult currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TResult currentElement, ref TKey currentKey)
             {
                 Debug.Assert(_sharedIndices != null);
 
@@ -199,10 +200,10 @@ namespace System.Linq.Parallel
 
                     // Enter the search phase. In this phase, all partitions race to populate
                     // the shared indices with their first 'count' contiguous elements.
-                    TResult current = default(TResult);
-                    TKey index = default(TKey);
+                    TResult current = default(TResult)!;
+                    TKey index = default(TKey)!;
                     int i = 0; //counter to help with cancellation
-                    while (buffer.Count < _count && _source.MoveNext(ref current, ref index))
+                    while (buffer.Count < _count && _source.MoveNext(ref current!, ref index))
                     {
                         if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                             CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -235,6 +236,7 @@ namespace System.Linq.Parallel
                 // index of the 'count'-th input element.
                 if (_take)
                 {
+                    Debug.Assert(_buffer != null && _bufferIndex != null);
                     // In the case of a Take, we will yield each element from our buffer for which
                     // the element is lesser than the 'count'-th index found.
                     if (_count == 0 || _bufferIndex.Value >= _buffer.Count - 1)
@@ -253,7 +255,7 @@ namespace System.Linq.Parallel
                 }
                 else
                 {
-                    TKey minKey = default(TKey);
+                    TKey minKey = default(TKey)!;
 
                     // If the count to skip was greater than 0, look at the buffer.
                     if (_count > 0)
@@ -266,6 +268,7 @@ namespace System.Linq.Parallel
 
                         minKey = _sharedIndices.MaxValue;
 
+                        Debug.Assert(_buffer != null && _bufferIndex != null);
                         // In the case of a skip, we must skip over elements whose index is lesser than the
                         // 'count'-th index found. Once we've exhausted the buffer, we must go back and continue
                         // enumerating the data source until it is empty.
@@ -286,7 +289,7 @@ namespace System.Linq.Parallel
                     }
 
                     // Lastly, so long as our input still has elements, they will be yieldable.
-                    if (_source.MoveNext(ref currentElement, ref currentKey))
+                    if (_source.MoveNext(ref currentElement!, ref currentKey))
                     {
                         Debug.Assert(_count <= 0 || _keyComparer.Compare(currentKey, minKey) > 0,
                                         "expected remaining element indices to be greater than smallest");
index a503ab53607d6135a562d4cb89beddc12e712f38..5ef627c9e91844e0332d4d4ff1fddc56c2086e46 100644 (file)
@@ -11,6 +11,7 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -42,8 +43,8 @@ namespace System.Linq.Parallel
     {
         // Predicate function used to decide when to stop yielding elements. One pair is used for
         // index-based evaluation (i.e. it is passed the index as well as the element's value).
-        private readonly Func<TResult, bool> _predicate;
-        private readonly Func<TResult, int, bool> _indexedPredicate;
+        private readonly Func<TResult, bool>? _predicate;
+        private readonly Func<TResult, int, bool>? _indexedPredicate;
 
         private readonly bool _take; // Whether to take (true) or skip (false).
         private bool _prematureMerge = false; // Whether to prematurely merge the input of this operator.
@@ -64,8 +65,8 @@ namespace System.Linq.Parallel
         //
 
         internal TakeOrSkipWhileQueryOperator(IEnumerable<TResult> child,
-                                              Func<TResult, bool> predicate,
-                                              Func<TResult, int, bool> indexedPredicate, bool take)
+                                              Func<TResult, bool>? predicate,
+                                              Func<TResult, int, bool>? indexedPredicate, bool take)
             : base(child)
         {
             Debug.Assert(child != null, "child data source cannot be null");
@@ -133,7 +134,7 @@ namespace System.Linq.Parallel
             CountdownEvent sharedBarrier = new CountdownEvent(partitionCount);
 
             Debug.Assert(_indexedPredicate == null || typeof(TKey) == typeof(int));
-            Func<TResult, TKey, bool> convertedIndexedPredicate = (Func<TResult, TKey, bool>)(object)_indexedPredicate;
+            Func<TResult, TKey, bool>? convertedIndexedPredicate = (Func<TResult, TKey, bool>?)(object?)_indexedPredicate;
 
             PartitionedStream<TResult, TKey> partitionedStream =
                 new PartitionedStream<TResult, TKey>(partitionCount, inputStream.KeyComparer, OrdinalIndexState);
@@ -171,6 +172,7 @@ namespace System.Linq.Parallel
                     return Child.AsSequentialQuery(token).TakeWhile(_indexedPredicate);
                 }
 
+                Debug.Assert(_predicate != null);
                 return Child.AsSequentialQuery(token).TakeWhile(_predicate);
             }
 
@@ -180,6 +182,7 @@ namespace System.Linq.Parallel
                 return wrappedIndexedChild.SkipWhile(_indexedPredicate);
             }
 
+            Debug.Assert(_predicate != null);
             IEnumerable<TResult> wrappedChild = CancellableEnumerable.Wrap(Child.AsSequentialQuery(token), token);
             return wrappedChild.SkipWhile(_predicate);
         }
@@ -201,8 +204,8 @@ namespace System.Linq.Parallel
         private class TakeOrSkipWhileQueryOperatorEnumerator<TKey> : QueryOperatorEnumerator<TResult, TKey>
         {
             private readonly QueryOperatorEnumerator<TResult, TKey> _source; // The data source to enumerate.
-            private readonly Func<TResult, bool> _predicate;  // The actual predicate function.
-            private readonly Func<TResult, TKey, bool> _indexedPredicate;  // The actual index-based predicate function.
+            private readonly Func<TResult, bool>? _predicate;  // The actual predicate function.
+            private readonly Func<TResult, TKey, bool>? _indexedPredicate;  // The actual index-based predicate function.
             private readonly bool _take; // Whether to execute a take- (true) or skip-while (false).
             private readonly IComparer<TKey> _keyComparer; // Comparer for the order keys.
 
@@ -211,10 +214,10 @@ namespace System.Linq.Parallel
             private readonly CountdownEvent _sharedBarrier; // To separate the search/yield phases.
             private readonly CancellationToken _cancellationToken; // Token used to cancel this operator.
 
-            private List<Pair<TResult, TKey>> _buffer; // Our buffer.
-            private Shared<int> _bufferIndex; // Our current index within the buffer.  [allocate in moveNext to avoid false-sharing]
+            private List<Pair<TResult, TKey>>? _buffer; // Our buffer.
+            private Shared<int>? _bufferIndex; // Our current index within the buffer.  [allocate in moveNext to avoid false-sharing]
             private int _updatesSeen; // How many updates has this enumerator observed? (Each other enumerator will contribute one update.)
-            private TKey _currentLowKey; // The lowest key rejected by one of the other enumerators.
+            private TKey _currentLowKey = default!; // The lowest key rejected by one of the other enumerators.
 
 
             //---------------------------------------------------------------------------------------
@@ -222,7 +225,7 @@ namespace System.Linq.Parallel
             //
 
             internal TakeOrSkipWhileQueryOperatorEnumerator(
-                QueryOperatorEnumerator<TResult, TKey> source, Func<TResult, bool> predicate, Func<TResult, TKey, bool> indexedPredicate, bool take,
+                QueryOperatorEnumerator<TResult, TKey> source, Func<TResult, bool>? predicate, Func<TResult, TKey, bool>? indexedPredicate, bool take,
                 OperatorState<TKey> operatorState, CountdownEvent sharedBarrier, CancellationToken cancelToken, IComparer<TKey> keyComparer)
             {
                 Debug.Assert(source != null);
@@ -245,7 +248,7 @@ namespace System.Linq.Parallel
             // Straightforward IEnumerator<T> methods.
             //
 
-            internal override bool MoveNext(ref TResult currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TResult currentElement, ref TKey currentKey)
             {
                 // If the buffer has not been created, we will generate it lazily on demand.
                 if (_buffer == null)
@@ -261,10 +264,10 @@ namespace System.Linq.Parallel
 
                     try
                     {
-                        TResult current = default(TResult);
-                        TKey key = default(TKey);
+                        TResult current = default(TResult)!;
+                        TKey key = default(TKey)!;
                         int i = 0; //counter to help with cancellation
-                        while (_source.MoveNext(ref current, ref key))
+                        while (_source.MoveNext(ref current!, ref key))
                         {
                             if ((i++ & CancellationState.POLL_INTERVAL) == 0)
                                 CancellationState.ThrowIfCanceled(_cancellationToken);
@@ -332,6 +335,7 @@ namespace System.Linq.Parallel
                     _bufferIndex = new Shared<int>(-1);
                 }
 
+                Debug.Assert(_bufferIndex != null);
                 // Now either enter (or continue) the yielding phase. As soon as we reach this, we know the
                 // current shared "low false" value is the absolute lowest with a false.
                 if (_take)
@@ -377,7 +381,7 @@ namespace System.Linq.Parallel
                     }
 
                     // Lastly, so long as our input still has elements, they will be yieldable.
-                    if (_source.MoveNext(ref currentElement, ref currentKey))
+                    if (_source.MoveNext(ref currentElement!, ref currentKey))
                     {
                         Debug.Assert(_keyComparer.Compare(currentKey, _operatorState._currentLowKey) > 0,
                                         "expected remaining element indices to be greater than smallest");
@@ -397,7 +401,7 @@ namespace System.Linq.Parallel
         private class OperatorState<TKey>
         {
             internal volatile int _updatesDone = 0;
-            internal TKey _currentLowKey;
+            internal TKey _currentLowKey = default!;
         }
     }
 }
index 3141a958b1d12c3119ac2180aab747d710fa1f91..7b772353f89ced51950831e243ab9d3e2f43495d 100644 (file)
@@ -10,6 +10,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -104,7 +105,7 @@ namespace System.Linq.Parallel
             private readonly QueryOperatorEnumerator<TInputOutput, TKey> _source; // The data source to enumerate.
             private readonly Func<TInputOutput, bool> _predicate; // The predicate used for filtering.
             private readonly CancellationToken _cancellationToken;
-            private Shared<int> _outputLoopCount;
+            private Shared<int>? _outputLoopCount;
 
             //-----------------------------------------------------------------------------------
             // Instantiates a new enumerator.
@@ -125,7 +126,7 @@ namespace System.Linq.Parallel
             // Moves to the next matching element in the underlying data stream.
             //
 
-            internal override bool MoveNext(ref TInputOutput currentElement, ref TKey currentKey)
+            internal override bool MoveNext([MaybeNullWhen(false), AllowNull] ref TInputOutput currentElement, ref TKey currentKey)
             {
                 Debug.Assert(_predicate != null, "expected a compiled operator");
 
@@ -135,7 +136,7 @@ namespace System.Linq.Parallel
                 if (_outputLoopCount == null)
                     _outputLoopCount = new Shared<int>(0);
 
-                while (_source.MoveNext(ref currentElement, ref currentKey))
+                while (_source.MoveNext(ref currentElement!, ref currentKey))
                 {
                     if ((_outputLoopCount.Value++ & CancellationState.POLL_INTERVAL) == 0)
                         CancellationState.ThrowIfCanceled(_cancellationToken);
index 5c6a9e56fe13018dd3a99bb1e1698672555370b7..41b2e58ec160435b0cd0256e944db8c3ec94352c 100644 (file)
@@ -110,6 +110,7 @@ namespace System.Linq.Parallel
             {
                 Debug.Assert(IsIndexible == (_op.OrdinalIndexState == OrdinalIndexState.Indexable));
 
+                Debug.Assert(_settings.ExecutionMode != null && _settings.DegreeOfParallelism != null);
                 if (_settings.ExecutionMode.Value == ParallelExecutionMode.Default && _op.LimitsParallelism)
                 {
                     // We need to run the query sequentially, up to and including this operator
index d90568b1213011c3263e562ad5c8f235a9d5707a..e0adf123b36fce90180bf3dc88345a5aa1dc1b7b 100644 (file)
@@ -19,7 +19,7 @@ namespace System.Linq.Parallel
     internal class CancellationState
     {
         // a cancellation signal that can be set internally to prompt early query termination.
-        internal CancellationTokenSource InternalCancellationTokenSource;
+        internal CancellationTokenSource? InternalCancellationTokenSource;
 
         // the external cancellationToken that the user sets to ask for the query to terminate early.
         // this has to be tracked explicitly so that an OCE(externalToken) can be thrown as the query
@@ -27,7 +27,7 @@ namespace System.Linq.Parallel
         internal CancellationToken ExternalCancellationToken;
 
         // A combined token Source for internal/external cancellation, defining the total cancellation state.
-        internal CancellationTokenSource MergedCancellationTokenSource;
+        internal CancellationTokenSource? MergedCancellationTokenSource;
 
         // A combined token for internal/external cancellation, defining the total cancellation state.
         internal CancellationToken MergedCancellationToken
index fafefc6233df0f2fca88cfbd14450ee22f1fdd8f..82f2c8d32984b12d8c27a7d879f028fb3a574dde 100644 (file)
@@ -87,8 +87,8 @@ namespace System.Linq.Parallel
         /// </summary>
         protected override void SpoolingWork()
         {
-            TOutput element = default(TOutput);
-            TKey key = default(TKey);
+            TOutput element = default(TOutput)!;
+            TKey key = default(TKey)!;
 
             int chunkSize = _autoBuffered ? PRODUCER_BUFFER_AUTO_SIZE : 1;
             Pair<TKey, TOutput>[] chunk = new Pair<TKey, TOutput>[chunkSize];
@@ -99,7 +99,7 @@ namespace System.Linq.Parallel
             do
             {
                 lastChunkSize = 0;
-                while (lastChunkSize < chunkSize && partition.MoveNext(ref element, ref key))
+                while (lastChunkSize < chunkSize && partition.MoveNext(ref element!, ref key))
                 {
                     chunk[lastChunkSize] = new Pair<TKey, TOutput>(key, element);
                     lastChunkSize++;
index f3f0232ae2eaa2f7b82e93c2cc0b1dce9b03edd2..44be53c47497f8f0eef0682e93edaee4e18dbaf9 100644 (file)
@@ -25,7 +25,7 @@ namespace System.Linq.Parallel
     /// <typeparam name="TKey"></typeparam>
     internal class OrderPreservingSpoolingTask<TInputOutput, TKey> : SpoolingTaskBase
     {
-        private readonly Shared<TInputOutput[]> _results; // The destination array cell into which data is placed.
+        private readonly Shared<TInputOutput[]?> _results; // The destination array cell into which data is placed.
         private readonly SortHelper<TInputOutput> _sortHelper; // A helper that performs the sorting.
 
         //-----------------------------------------------------------------------------------
@@ -43,7 +43,7 @@ namespace System.Linq.Parallel
 
         private OrderPreservingSpoolingTask(
             int taskIndex, QueryTaskGroupState groupState,
-            Shared<TInputOutput[]> results, SortHelper<TInputOutput> sortHelper) :
+            Shared<TInputOutput[]?> results, SortHelper<TInputOutput> sortHelper) :
             base(taskIndex, groupState)
         {
             Debug.Assert(groupState != null);
@@ -70,7 +70,7 @@ namespace System.Linq.Parallel
 
         internal static void Spool(
             QueryTaskGroupState groupState, PartitionedStream<TInputOutput, TKey> partitions,
-            Shared<TInputOutput[]> results, TaskScheduler taskScheduler)
+            Shared<TInputOutput[]?> results, TaskScheduler taskScheduler)
         {
             Debug.Assert(groupState != null);
             Debug.Assert(partitions != null);
index e427f6f1ff8fd119e19189febbdb5e8f5ac36427..714e65472d3d4ad1cdc2792a5d29dbcbd962b2fd 100644 (file)
@@ -42,8 +42,9 @@ namespace System.Linq.Parallel
         // A static function used by s_runTaskSynchronouslyDelegate, which is used by RunSynchronously
         //
 
-        private static void RunTaskSynchronously(object o)
+        private static void RunTaskSynchronously(object? o)
         {
+            Debug.Assert(o != null);
             ((QueryTask)o).BaseWork(null);
         }
 
@@ -51,7 +52,7 @@ namespace System.Linq.Parallel
         // A static delegate used by RunSynchronously
         //
 
-        private static readonly Action<object> s_runTaskSynchronouslyDelegate = RunTaskSynchronously;
+        private static readonly Action<object?> s_runTaskSynchronouslyDelegate = RunTaskSynchronously;
 
         //-----------------------------------------------------------------------------------
         // Executes the task synchronously (on the current thread).
@@ -70,8 +71,9 @@ namespace System.Linq.Parallel
         // Executes the task asynchronously (elsewhere, unspecified).
         //
 
-        private static readonly Action<object> s_baseWorkDelegate = delegate (object o)
+        private static readonly Action<object?> s_baseWorkDelegate = delegate (object? o)
         {
+            Debug.Assert(o != null);
             ((QueryTask)o).BaseWork(null);
         };
 
@@ -88,7 +90,7 @@ namespace System.Linq.Parallel
         // amount of tracing around the call to the real work API.
         //
 
-        private void BaseWork(object unused)
+        private void BaseWork(object? unused)
         {
             Debug.Assert(unused == null);
             TraceHelpers.TraceInfo("[timing]: {0}: Start work {1}", DateTime.Now.Ticks, _taskIndex);
index 297fe4c5c5d520ff13d72dd11ee373906f443461..0109c7e68967d63ede5becbc94f00edf12161654 100644 (file)
@@ -22,7 +22,7 @@ namespace System.Linq.Parallel
     /// </summary>
     internal class QueryTaskGroupState
     {
-        private Task _rootTask; // The task under which all query tasks root.
+        private Task? _rootTask; // The task under which all query tasks root.
         private int _alreadyEnded; // Whether the tasks have been waited on already.
         private readonly CancellationState _cancellationState; // The cancellation state.
         private readonly int _queryId; // Id of this query execution.
@@ -112,7 +112,7 @@ namespace System.Linq.Parallel
                     bool allOCEsOnTrackedExternalCancellationToken = true;
                     for (int i = 0; i < flattenedAE.InnerExceptions.Count; i++)
                     {
-                        OperationCanceledException oce = flattenedAE.InnerExceptions[i] as OperationCanceledException;
+                        OperationCanceledException? oce = flattenedAE.InnerExceptions[i] as OperationCanceledException;
 
                         // we only let it pass through iff:
                         // it is not null, not default, and matches the exact token we were given as being the external token
index c75997dfefad5d45d8e8b7daeb05153c3bafc15a..3087025ef6df0b752b9f9052b3b1278123e7b5cb 100644 (file)
@@ -78,7 +78,7 @@ namespace System.Linq.Parallel
             // Because of the lack of typeof(T).IsValueType we need two pieces of information
             // to determine this. default(T) will return a non null for Value Types, except those
             // using Nullable<>, that is why we need a second condition.
-            if (default(T) != null || Nullable.GetUnderlyingType(typeof(T)) != null)
+            if (default(T)! != null || Nullable.GetUnderlyingType(typeof(T)) != null)
             {
                 // Marshal.SizeOf fails for value types that don't have explicit layouts. We
                 // just fall back to some arbitrary constant in that case. Is there a better way?
index 17c94785e61eae29ee294f1017fd4f8cf49aa788..4389622e59acd197b7cd89e7f305ab563fa3f8ff 100644 (file)
@@ -216,15 +216,15 @@ namespace System.Linq.Parallel
         {
             // We just enumerate over the entire source data stream, placing each element
             // into the destination channel.
-            TInputOutput current = default(TInputOutput);
-            TIgnoreKey keyUnused = default(TIgnoreKey);
+            TInputOutput current = default(TInputOutput)!;
+            TIgnoreKey keyUnused = default(TIgnoreKey)!;
 
             QueryOperatorEnumerator<TInputOutput, TIgnoreKey> source = _source;
             SynchronousChannel<TInputOutput> destination = _destination;
             CancellationToken cancelToken = _groupState.CancellationState.MergedCancellationToken;
 
             destination.Init();
-            while (source.MoveNext(ref current, ref keyUnused))
+            while (source.MoveNext(ref current!, ref keyUnused))
             {
                 // If an abort has been requested, stop this worker immediately.
                 if (cancelToken.IsCancellationRequested)
@@ -305,14 +305,14 @@ namespace System.Linq.Parallel
         {
             // We just enumerate over the entire source data stream, placing each element
             // into the destination channel.
-            TInputOutput current = default(TInputOutput);
-            TIgnoreKey keyUnused = default(TIgnoreKey);
+            TInputOutput current = default(TInputOutput)!;
+            TIgnoreKey keyUnused = default(TIgnoreKey)!;
 
             QueryOperatorEnumerator<TInputOutput, TIgnoreKey> source = _source;
             AsynchronousChannel<TInputOutput> destination = _destination;
             CancellationToken cancelToken = _groupState.CancellationState.MergedCancellationToken;
 
-            while (source.MoveNext(ref current, ref keyUnused))
+            while (source.MoveNext(ref current!, ref keyUnused))
             {
                 // If an abort has been requested, stop this worker immediately.
                 if (cancelToken.IsCancellationRequested)
@@ -390,11 +390,11 @@ namespace System.Linq.Parallel
         protected override void SpoolingWork()
         {
             // We just enumerate over the entire source data stream for effect.
-            TInputOutput currentUnused = default(TInputOutput);
-            TIgnoreKey keyUnused = default(TIgnoreKey);
+            TInputOutput currentUnused = default(TInputOutput)!;
+            TIgnoreKey keyUnused = default(TIgnoreKey)!;
 
             //Note: this only ever runs with a ForAll operator, and ForAllEnumerator performs cancellation checks
-            while (_source.MoveNext(ref currentUnused, ref keyUnused))
+            while (_source.MoveNext(ref currentUnused!, ref keyUnused))
                 ;
         }
 
index d2668de3f242a7a57bf46af03e49c848a217d734..6250798ad6a0323fba1abd17c998146fbdf6a25a 100644 (file)
@@ -9,6 +9,7 @@
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Threading;
 
 namespace System.Linq.Parallel
@@ -48,8 +49,7 @@ namespace System.Linq.Parallel
             }
             catch (Exception ex)
             {
-                OperationCanceledException oce = ex as OperationCanceledException;
-                if (oce != null &&
+                if (ex is OperationCanceledException oce &&
                     oce.CancellationToken == _groupState.CancellationState.MergedCancellationToken
                     && _groupState.CancellationState.MergedCancellationToken.IsCancellationRequested)
                 {
@@ -60,6 +60,7 @@ namespace System.Linq.Parallel
                     // TPL will catch and store the exception on the task object. We'll then later
                     // turn around and wait on it, having the effect of propagating it. In the meantime,
                     // we want to cooperative cancel all workers.
+                    Debug.Assert(_groupState.CancellationState.InternalCancellationTokenSource != null);
                     _groupState.CancellationState.InternalCancellationTokenSource.Cancel();
 
                     // And then repropagate to let TPL catch it.
index ca012c99f8863b8d54eafa502531303928e0d3bd..3a8594393b875a1d09c60ddcecb59ee8990768ea 100644 (file)
@@ -32,7 +32,7 @@ namespace System.Linq.Parallel
             {
                 while (true)
                 {
-                    TElement elem = default(TElement);
+                    TElement elem = default(TElement)!;
                     try
                     {
                         if (!enumerator.MoveNext())
@@ -66,8 +66,8 @@ namespace System.Linq.Parallel
         internal static IEnumerable<TElement> WrapQueryEnumerator<TElement, TIgnoreKey>(QueryOperatorEnumerator<TElement, TIgnoreKey> source,
             CancellationState cancellationState)
         {
-            TElement elem = default(TElement);
-            TIgnoreKey ignoreKey = default(TIgnoreKey);
+            TElement elem = default(TElement)!;
+            TIgnoreKey ignoreKey = default(TIgnoreKey)!;
 
             try
             {
@@ -75,7 +75,7 @@ namespace System.Linq.Parallel
                 {
                     try
                     {
-                        if (!source.MoveNext(ref elem, ref ignoreKey))
+                        if (!source.MoveNext(ref elem!, ref ignoreKey))
                         {
                             yield break;
                         }
@@ -136,7 +136,7 @@ namespace System.Linq.Parallel
         {
             return t =>
                 {
-                    U retval = default(U);
+                    U retval = default(U)!;
                     try
                     {
                         retval = f(t);
@@ -165,23 +165,22 @@ namespace System.Linq.Parallel
             // See QueryTaskGroupState.WaitAll for the main plinq exception handling logic.
 
             // check for co-operative cancellation.
-            OperationCanceledException cancelEx = ex as OperationCanceledException;
-            if (cancelEx != null &&
-                cancelEx.CancellationToken == cancellationState.ExternalCancellationToken
-                && cancellationState.ExternalCancellationToken.IsCancellationRequested)
+            if (ex is OperationCanceledException cancelEx)
             {
-                return true;  // let the OCE(extCT) be rethrown.
-            }
+                if (cancelEx.CancellationToken == cancellationState.ExternalCancellationToken
+                    && cancellationState.ExternalCancellationToken.IsCancellationRequested)
+                {
+                    return true;  // let the OCE(extCT) be rethrown.
+                }
 
-            // check for external cancellation which triggered the mergedToken.
-            if (cancelEx != null &&
-                cancelEx.CancellationToken == cancellationState.MergedCancellationToken
-                && cancellationState.MergedCancellationToken.IsCancellationRequested
-                && cancellationState.ExternalCancellationToken.IsCancellationRequested)
-            {
-                return true;  // convert internal cancellation back to OCE(extCT).
+                // check for external cancellation which triggered the mergedToken.
+                if (cancelEx.CancellationToken == cancellationState.MergedCancellationToken
+                    && cancellationState.MergedCancellationToken.IsCancellationRequested
+                    && cancellationState.ExternalCancellationToken.IsCancellationRequested)
+                {
+                    return true;  // convert internal cancellation back to OCE(extCT).
+                }
             }
-
             return false;
         }
     }
index 7aa26e30962103b4e6e928d0f9534a986639690d..abc59de1408431366fc76e573414bec6afd0023f 100644 (file)
@@ -35,8 +35,7 @@ namespace System.Linq.Parallel
             // The partitioned stream to return.
             PartitionedStream<T, int> returnValue;
 
-            IParallelPartitionable<T> sourceAsPartitionable = source as IParallelPartitionable<T>;
-            if (sourceAsPartitionable != null)
+            if (source is IParallelPartitionable<T> sourceAsPartitionable)
             {
                 // The type overrides the partitioning algorithm, so we will use it instead of the default.
                 // The returned enumerator must be the same size that we requested, otherwise we throw.
@@ -89,16 +88,16 @@ namespace System.Linq.Parallel
         //
 
         internal static PartitionedStream<Pair<TElement, THashKey>, int> HashRepartition<TElement, THashKey, TIgnoreKey>(
-            PartitionedStream<TElement, TIgnoreKey> source, Func<TElement, THashKey> keySelector, IEqualityComparer<THashKey> keyComparer,
-            IEqualityComparer<TElement> elementComparer, CancellationToken cancellationToken)
+            PartitionedStream<TElement, TIgnoreKey> source, Func<TElement, THashKey>? keySelector, IEqualityComparer<THashKey>? keyComparer,
+            IEqualityComparer<TElement>? elementComparer, CancellationToken cancellationToken)
         {
             TraceHelpers.TraceInfo("PartitionStream<..>.HashRepartitionStream(..):: creating **RE**partitioned stream for nested operator");
             return new UnorderedHashRepartitionStream<TElement, THashKey, TIgnoreKey>(source, keySelector, keyComparer, elementComparer, cancellationToken);
         }
 
         internal static PartitionedStream<Pair<TElement, THashKey>, TOrderKey> HashRepartitionOrdered<TElement, THashKey, TOrderKey>(
-            PartitionedStream<TElement, TOrderKey> source, Func<TElement, THashKey> keySelector, IEqualityComparer<THashKey> keyComparer,
-            IEqualityComparer<TElement> elementComparer, CancellationToken cancellationToken)
+            PartitionedStream<TElement, TOrderKey> source, Func<TElement, THashKey>? keySelector, IEqualityComparer<THashKey>? keyComparer,
+            IEqualityComparer<TElement>? elementComparer, CancellationToken cancellationToken)
         {
             TraceHelpers.TraceInfo("PartitionStream<..>.HashRepartitionStream(..):: creating **RE**partitioned stream for nested operator");
             return new OrderedHashRepartitionStream<TElement, THashKey, TOrderKey>(source, keySelector, keyComparer, elementComparer, cancellationToken);
index dd8d122f5dbc282cd1973cd42223fdee34b75ccf..9c1df2afac3a81bd1ec936f4a49076540f54c4ae 100644 (file)
@@ -9,6 +9,7 @@
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq.Parallel
 {
@@ -23,7 +24,7 @@ namespace System.Linq.Parallel
         private Slot[] slots;
         private int count;
         private int freeList;
-        private readonly IEqualityComparer<TKey> comparer;
+        private readonly IEqualityComparer<TKey>? comparer;
 
         private const int HashCodeMask = 0x7fffffff;
 
@@ -31,7 +32,7 @@ namespace System.Linq.Parallel
         {
         }
 
-        internal HashLookup(IEqualityComparer<TKey> comparer)
+        internal HashLookup(IEqualityComparer<TKey>? comparer)
         {
             this.comparer = comparer;
             buckets = new int[7];
@@ -46,7 +47,7 @@ namespace System.Linq.Parallel
         }
 
         // Check whether value is in set
-        internal bool TryGetValue(TKey key, ref TValue value)
+        internal bool TryGetValue(TKey key, [MaybeNullWhen(false), AllowNull] ref TValue value)
         {
             return Find(key, false, false, ref value);
         }
index df7c29db0944aa4133e46a5fbb80d597003d8ac1..28034dcb0657073ab40a73cbf4bbb1f856c657ba 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Linq.Parallel
     {
         internal TInputOutput[] _chunk;
         private int _chunkCount;
-        private ListChunk<TInputOutput> _nextChunk;
+        private ListChunk<TInputOutput>? _nextChunk;
         private ListChunk<TInputOutput> _tailChunk;
 
         /// <summary>
@@ -54,7 +54,7 @@ namespace System.Linq.Parallel
         /// <summary>
         /// The next chunk in the linked chain.
         /// </summary>
-        internal ListChunk<TInputOutput> Next
+        internal ListChunk<TInputOutput>? Next
         {
             get { return _nextChunk; }
         }
@@ -72,7 +72,7 @@ namespace System.Linq.Parallel
         /// </summary>
         public IEnumerator<TInputOutput> GetEnumerator()
         {
-            ListChunk<TInputOutput> curr = this;
+            ListChunk<TInputOutput>? curr = this;
             while (curr != null)
             {
                 for (int i = 0; i < curr._chunkCount; i++)
index 2803a7d87bd43deaf75e8b4875a39236d49b8ed7..a871131348730fb214c55284da11dc8e29b58797 100644 (file)
@@ -35,11 +35,11 @@ namespace System.Linq.Parallel
     /// </summary>
     /// <typeparam name="TKey"></typeparam>
     /// <typeparam name="TElement"></typeparam>
-    internal class Lookup<TKey, TElement> : ILookup<TKey, TElement>
+    internal class Lookup<TKey, TElement> : ILookup<TKey, TElement> where TKey: notnull
     {
         private readonly IDictionary<TKey, IGrouping<TKey, TElement>> _dict;
         private readonly IEqualityComparer<TKey> _comparer;
-        private IGrouping<TKey, TElement> _defaultKeyGrouping = null;
+        private IGrouping<TKey, TElement>? _defaultKeyGrouping = null;
 
         internal Lookup(IEqualityComparer<TKey> comparer)
         {
@@ -66,7 +66,7 @@ namespace System.Linq.Parallel
         {
             get
             {
-                if (_comparer.Equals(key, default(TKey)))
+                if (_comparer.Equals(key, default))
                 {
                     if (_defaultKeyGrouping != null)
                     {
@@ -77,7 +77,7 @@ namespace System.Linq.Parallel
                 }
                 else
                 {
-                    IGrouping<TKey, TElement> grouping;
+                    IGrouping<TKey, TElement>? grouping;
                     if (_dict.TryGetValue(key, out grouping))
                     {
                         return grouping;
@@ -90,7 +90,7 @@ namespace System.Linq.Parallel
 
         public bool Contains(TKey key)
         {
-            if (_comparer.Equals(key, default(TKey)))
+            if (_comparer.Equals(key, default))
             {
                 return _defaultKeyGrouping != null;
             }
@@ -111,7 +111,7 @@ namespace System.Linq.Parallel
 
         internal void Add(IGrouping<TKey, TElement> grouping)
         {
-            if (_comparer.Equals(grouping.Key, default(TKey)))
+            if (_comparer.Equals(grouping.Key, default))
             {
                 Debug.Assert(_defaultKeyGrouping == null, "Cannot insert two groupings with the default key into a lookup.");
 
index 67c02a3c7ebd7b984f20a84773cd084adf5fb55b..3160e64cf62741651c5d6149521e32a8e366a1e1 100644 (file)
@@ -8,6 +8,8 @@
 //
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
+using System.Diagnostics.CodeAnalysis;
+
 namespace System.Linq.Parallel
 {
     /// <summary>
@@ -27,7 +29,7 @@ namespace System.Linq.Parallel
         // A simple constructor that initializes the first/second fields.
         //
 
-        public Pair(T first, U second)
+        public Pair(T first, [MaybeNull, AllowNull] U second)
         {
             _first = first;
             _second = second;
@@ -49,4 +51,4 @@ namespace System.Linq.Parallel
             set { _second = value; }
         }
     }
-}
\ No newline at end of file
+}
index 0080077e5cd809b74e1c1ef21470de21cfd14736..4968cfaddc7278ce232c613433495886ec64f2b3 100644 (file)
@@ -21,9 +21,9 @@ namespace System.Linq.Parallel
     internal sealed class PairComparer<T, U> : IComparer<Pair<T, U>>
     {
         private readonly IComparer<T> _comparer1;
-        private readonly IComparer<U> _comparer2;
+        private readonly IComparer<U>? _comparer2;
 
-        public PairComparer(IComparer<T> comparer1, IComparer<U> comparer2)
+        public PairComparer(IComparer<T> comparer1, IComparer<U>? comparer2)
         {
             _comparer1 = comparer1;
             _comparer2 = comparer2;
@@ -37,6 +37,9 @@ namespace System.Linq.Parallel
                 return result1;
             }
 
+            if (_comparer2 == null)
+                return result1;
+
             return _comparer2.Compare(x.Second, y.Second);
         }
     }
index 9fc4d49029070ee0c6eb73fbe4434cc8620381de..863943a8d786daad37d0ad08f757d10b6b7aba75 100644 (file)
@@ -41,7 +41,7 @@ namespace System.Linq.Parallel
 
         // This data is shared among all partitions.
         private readonly QueryTaskGroupState _groupState; // To communicate status, e.g. cancellation.
-        private readonly int[][] _sharedIndices; // Shared set of indices used during sorting.
+        private readonly int[]?[] _sharedIndices; // Shared set of indices used during sorting.
         private readonly GrowingArray<TKey>[] _sharedKeys; // Shared keys with which to compare elements.
         private readonly TInputOutput[][] _sharedValues; // The actual values used for comparisons.
         private readonly Barrier[][] _sharedBarriers; // A matrix of barriers used for synchronizing during merges.
@@ -191,8 +191,8 @@ namespace System.Linq.Parallel
         internal override TInputOutput[] Sort()
         {
             // Step 1.  Accumulate this partitions' worth of input.
-            GrowingArray<TKey> sourceKeys = null;
-            List<TInputOutput> sourceValues = null;
+            GrowingArray<TKey>? sourceKeys = null;
+            List<TInputOutput>? sourceValues = null;
 
             BuildKeysFromSource(ref sourceKeys, ref sourceValues);
 
@@ -221,7 +221,7 @@ namespace System.Linq.Parallel
         //    Should only be called once per sort helper.
         //
 
-        private void BuildKeysFromSource(ref GrowingArray<TKey> keys, ref List<TInputOutput> values)
+        private void BuildKeysFromSource(ref GrowingArray<TKey>? keys, ref List<TInputOutput>? values)
         {
             values = new List<TInputOutput>();
 
@@ -229,9 +229,9 @@ namespace System.Linq.Parallel
             CancellationToken cancelToken = _groupState.CancellationState.MergedCancellationToken;
             try
             {
-                TInputOutput current = default(TInputOutput);
-                TKey currentKey = default(TKey);
-                bool hadNext = _source.MoveNext(ref current, ref currentKey);
+                TInputOutput current = default(TInputOutput)!;
+                TKey currentKey = default(TKey)!;
+                bool hadNext = _source.MoveNext(ref current!, ref currentKey);
 
                 if (keys == null)
                 {
@@ -250,7 +250,7 @@ namespace System.Linq.Parallel
                         keys.Add(currentKey);
                         values.Add(current);
                     }
-                    while (_source.MoveNext(ref current, ref currentKey));
+                    while (_source.MoveNext(ref current!, ref currentKey));
                 }
             }
             finally
@@ -375,7 +375,7 @@ namespace System.Linq.Parallel
                 if (partnerIndex < _partitionCount)
                 {
                     // Cache references to our local data.
-                    int[] myIndices = _sharedIndices[_partitionIndex];
+                    int[]? myIndices = _sharedIndices[_partitionIndex];
                     GrowingArray<TKey> myKeys = _sharedKeys[_partitionIndex];
                     TKey[] myKeysArr = myKeys.InternalArray;
 
@@ -396,7 +396,7 @@ namespace System.Linq.Parallel
                         // to hold the merged indices and key/value pairs.
 
                         // First, remember a copy of all of the partner's lists.
-                        int[] rightIndices = _sharedIndices[partnerIndex];
+                        int[]? rightIndices = _sharedIndices[partnerIndex];
                         TKey[] rightKeys = _sharedKeys[partnerIndex].InternalArray;
                         TInputOutput[] rightValues = _sharedValues[partnerIndex];
 
@@ -412,7 +412,7 @@ namespace System.Linq.Parallel
 
                         // Now allocate the lists into which the merged data will go.  Share this
                         // with the other thread so that it can place data into it as well.
-                        int[] mergedIndices = null;
+                        int[]? mergedIndices = null;
                         TInputOutput[] mergedValues = new TInputOutput[totalCount];
 
                         // Only on the last phase do we need to remember indices and keys.
@@ -436,6 +436,7 @@ namespace System.Linq.Parallel
                         // copy the values and not the indices or keys.
                         int m = (totalCount + 1) / 2;
                         int i = 0, j0 = 0, j1 = 0;
+                        Debug.Assert(myIndices != null);
                         while (i < m)
                         {
                             if ((i & CancellationState.POLL_INTERVAL) == 0)
@@ -443,7 +444,7 @@ namespace System.Linq.Parallel
 
                             if (j0 < leftCount && (j1 >= rightCount ||
                                                    _keyComparer.Compare(myKeysArr[myIndices[j0]],
-                                                                         rightKeys[rightIndices[j1]]) <= 0))
+                                                                         rightKeys[rightIndices![j1]]) <= 0))
                             {
                                 if (isLastPhase)
                                 {
@@ -451,18 +452,21 @@ namespace System.Linq.Parallel
                                 }
                                 else
                                 {
+                                    Debug.Assert(mergedIndices != null);
                                     mergedIndices[i] = myIndices[j0];
                                 }
                                 j0++;
                             }
                             else
                             {
+                                Debug.Assert(rightIndices != null);
                                 if (isLastPhase)
                                 {
                                     mergedValues[i] = rightValues[rightIndices[j1]];
                                 }
                                 else
                                 {
+                                    Debug.Assert(mergedIndices != null);
                                     mergedIndices[i] = leftCount + rightIndices[j1];
                                 }
                                 j1++;
@@ -489,10 +493,10 @@ namespace System.Linq.Parallel
                         // (1) its own indices, keys, and values, stored in the cell that used to hold our data,
                         // and (2) the arrays into which merged data will go, stored in its shared array cells.
                         // We will snag references to all of these things.
-                        int[] leftIndices = _sharedIndices[_partitionIndex];
+                        int[]? leftIndices = _sharedIndices[_partitionIndex];
                         TKey[] leftKeys = _sharedKeys[_partitionIndex].InternalArray;
                         TInputOutput[] leftValues = _sharedValues[_partitionIndex];
-                        int[] mergedIndices = _sharedIndices[partnerIndex];
+                        int[]? mergedIndices = _sharedIndices[partnerIndex];
                         GrowingArray<TKey> mergedKeys = _sharedKeys[partnerIndex];
                         TInputOutput[] mergedValues = _sharedValues[partnerIndex];
 
@@ -509,21 +513,24 @@ namespace System.Linq.Parallel
                         // copy the values and not the indices or keys.
                         int m = (totalCount + 1) / 2;
                         int i = totalCount - 1, j0 = leftCount - 1, j1 = rightCount - 1;
+                        Debug.Assert(myIndices != null);
                         while (i >= m)
                         {
                             if ((i & CancellationState.POLL_INTERVAL) == 0)
                                 CancellationState.ThrowIfCanceled(cancelToken);
 
                             if (j0 >= 0 && (j1 < 0 ||
-                                            _keyComparer.Compare(leftKeys[leftIndices[j0]],
+                                            _keyComparer.Compare(leftKeys[leftIndices![j0]],
                                                                   myKeysArr[myIndices[j1]]) > 0))
                             {
+                                Debug.Assert(leftIndices != null);
                                 if (isLastPhase)
                                 {
                                     mergedValues[i] = leftValues[leftIndices[j0]];
                                 }
                                 else
                                 {
+                                    Debug.Assert(mergedIndices != null);
                                     mergedIndices[i] = leftIndices[j0];
                                 }
                                 j0--;
@@ -536,6 +543,7 @@ namespace System.Linq.Parallel
                                 }
                                 else
                                 {
+                                    Debug.Assert(mergedIndices != null);
                                     mergedIndices[i] = leftCount + myIndices[j1];
                                 }
                                 j1--;
index 1124fbfebb8098d602ebcf29349763f242c268a9..4f447720e260c68bfd259d31fc9036452406594a 100644 (file)
@@ -22,7 +22,7 @@ namespace System.Linq.Parallel
     {
         private readonly IEqualityComparer<T> _comparer;
 
-        internal WrapperEqualityComparer(IEqualityComparer<T> comparer)
+        internal WrapperEqualityComparer(IEqualityComparer<T>? comparer)
         {
             if (comparer == null)
             {
index c99a8b73163bc5991b0a6acf6a8c8c88af916c6a..ec67f99d4ab3861d514919bbf0a6dacd7926fb26 100644 (file)
@@ -20,6 +20,7 @@ using System.Linq.Parallel;
 using System.Collections.Concurrent;
 using System.Collections;
 using System.Threading.Tasks;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.Linq
 {
@@ -152,8 +153,7 @@ namespace System.Linq
 
             if (!(source is ParallelEnumerableWrapper<TSource> || source is IParallelPartitionable<TSource>))
             {
-                PartitionerQueryOperator<TSource> partitionerOp = source as PartitionerQueryOperator<TSource>;
-                if (partitionerOp != null)
+                if (source is PartitionerQueryOperator<TSource>  partitionerOp)
                 {
                     if (!partitionerOp.Orderable)
                     {
@@ -194,13 +194,13 @@ namespace System.Linq
                 throw new ArgumentNullException(nameof(source));
             }
 
-            ParallelEnumerableWrapper wrapper = source as ParallelEnumerableWrapper;
+            ParallelEnumerableWrapper? wrapper = source as ParallelEnumerableWrapper;
             if (wrapper == null)
             {
                 throw new InvalidOperationException(SR.ParallelQuery_InvalidNonGenericAsOrderedCall);
             }
 
-            return new OrderingQueryOperator<object>(QueryOperator<object>.AsQueryOperator(wrapper), true);
+            return new OrderingQueryOperator<object?>(QueryOperator<object?>.AsQueryOperator(wrapper), true);
         }
 
         /// <summary>
@@ -270,8 +270,7 @@ namespace System.Linq
             if (source == null) throw new ArgumentNullException(nameof(source));
 
             // Ditch the wrapper, if there is one.
-            ParallelEnumerableWrapper<TSource> wrapper = source as ParallelEnumerableWrapper<TSource>;
-            if (wrapper != null)
+            if (source is ParallelEnumerableWrapper<TSource> wrapper)
             {
                 return wrapper.WrappedEnumerable;
             }
@@ -749,7 +748,7 @@ namespace System.Linq
         public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
             this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
             Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
-            Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null) throw new ArgumentNullException(nameof(outer));
             if (inner == null) throw new ArgumentNullException(nameof(inner));
@@ -786,7 +785,7 @@ namespace System.Linq
         public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult>(
             this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
             Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
-            Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -883,7 +882,7 @@ namespace System.Linq
         public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
             this ParallelQuery<TOuter> outer, ParallelQuery<TInner> inner,
             Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
-            Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (outer == null) throw new ArgumentNullException(nameof(outer));
             if (inner == null) throw new ArgumentNullException(nameof(inner));
@@ -921,7 +920,7 @@ namespace System.Linq
         public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
             this ParallelQuery<TOuter> outer, IEnumerable<TInner> inner,
             Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector,
-            Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -1097,7 +1096,7 @@ namespace System.Linq
         /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1151,7 +1150,7 @@ namespace System.Linq
         /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1212,7 +1211,7 @@ namespace System.Linq
         ///
 
         public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey>(
-            this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+            this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1273,7 +1272,7 @@ namespace System.Linq
         ///
 
         public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey>(
-            this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+            this OrderedParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1319,7 +1318,7 @@ namespace System.Linq
         /// <paramref name="source"/> or <paramref name="keySelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1372,7 +1371,7 @@ namespace System.Linq
         /// <paramref name="elementSelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -1439,7 +1438,7 @@ namespace System.Linq
         /// <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));
 
@@ -1500,7 +1499,7 @@ namespace System.Linq
         /// <paramref name="elementSelector"/> or <paramref name="resultSelector"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey>? comparer)
         {
             if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));
 
@@ -1524,7 +1523,6 @@ namespace System.Linq
         // Return Value:
         //     The result of aggregation.
         //
-
         private static T PerformAggregation<T>(this ParallelQuery<T> source,
             Func<T, T, T> reduce, T seed, bool seedIsSpecified, bool throwIfEmpty, QueryAggregationOptions options)
         {
@@ -1537,7 +1535,6 @@ namespace System.Linq
             return op.Aggregate();
         }
 
-
         /// <summary>
         /// Run an aggregation sequentially. If the user-provided reduction function throws an exception, wrap
         /// it with an AggregateException.
@@ -1571,7 +1568,7 @@ namespace System.Linq
                         throw new InvalidOperationException(SR.NoElements);
                     }
 
-                    acc = (TAccumulate)(object)enumerator.Current;
+                    acc = (TAccumulate)(object)enumerator.Current!;
                 }
 
                 while (enumerator.MoveNext())
@@ -1640,14 +1637,14 @@ namespace System.Linq
             {
                 // 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);
+                return source.PerformSequentialAggregation(default!, 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<TSource>(func, default(TSource), false, true, options);
+                return source.PerformAggregation<TSource>(func, default!, false, true, options);
             }
         }
 
@@ -1839,7 +1836,7 @@ namespace System.Linq
             if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector));
 
             return new AssociativeAggregationOperator<TSource, TAccumulate, TResult>(
-                source, default(TAccumulate), seedFactory, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
+                source, default!, seedFactory, true, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector,
                 false, QueryAggregationOptions.AssociativeCommutative).Aggregate();
         }
 
@@ -1870,11 +1867,9 @@ namespace System.Linq
             if (source == null) throw new ArgumentNullException(nameof(source));
 
             // If the data source is a collection, we can just return the count right away.
-            ParallelEnumerableWrapper<TSource> sourceAsWrapper = source as ParallelEnumerableWrapper<TSource>;
-            if (sourceAsWrapper != null)
+            if (source is ParallelEnumerableWrapper<TSource> sourceAsWrapper)
             {
-                ICollection<TSource> sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection<TSource>;
-                if (sourceAsCollection != null)
+                if (sourceAsWrapper.WrappedEnumerable is ICollection<TSource> sourceAsCollection)
                 {
                     return sourceAsCollection.Count;
                 }
@@ -1943,11 +1938,9 @@ namespace System.Linq
             if (source == null) throw new ArgumentNullException(nameof(source));
 
             // If the data source is a collection, we can just return the count right away.
-            ParallelEnumerableWrapper<TSource> sourceAsWrapper = source as ParallelEnumerableWrapper<TSource>;
-            if (sourceAsWrapper != null)
+            if (source is ParallelEnumerableWrapper<TSource> sourceAsWrapper)
             {
-                ICollection<TSource> sourceAsCollection = sourceAsWrapper.WrappedEnumerable as ICollection<TSource>;
-                if (sourceAsCollection != null)
+                if (sourceAsWrapper.WrappedEnumerable is ICollection<TSource> sourceAsCollection)
                 {
                     return sourceAsCollection.Count;
                 }
@@ -2681,6 +2674,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource Min<TSource>(this ParallelQuery<TSource> source)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -2943,6 +2937,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TResult Min<TSource, TResult>(this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
         {
             return source.Select<TSource, TResult>(selector).Min<TResult>();
@@ -3184,6 +3179,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource Max<TSource>(this ParallelQuery<TSource> source)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -3446,6 +3442,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TResult Max<TSource, TResult>(this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
         {
             return source.Select<TSource, TResult>(selector).Max<TResult>();
@@ -4051,7 +4048,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
-        public static bool Contains<TSource>(this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
+        public static bool Contains<TSource>(this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
 
@@ -4348,7 +4345,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
-        public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
+        public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             if (first == null) throw new ArgumentNullException(nameof(first));
             if (second == null) throw new ArgumentNullException(nameof(second));
@@ -4443,7 +4440,7 @@ namespace System.Linq
         /// but would in reality bind to sequential implementation.
         /// </remarks>
         [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
-        public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        public static bool SequenceEqual<TSource>(this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -4480,7 +4477,7 @@ namespace System.Linq
         /// <paramref name="source"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TSource> Distinct<TSource>(
-            this ParallelQuery<TSource> source, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> source, IEqualityComparer<TSource>? comparer)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
 
@@ -4541,7 +4538,7 @@ namespace System.Linq
         /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TSource> Union<TSource>(
-            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             if (first == null) throw new ArgumentNullException(nameof(first));
             if (second == null) throw new ArgumentNullException(nameof(second));
@@ -4567,7 +4564,7 @@ namespace System.Linq
         /// </remarks>
         [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
         public static ParallelQuery<TSource> Union<TSource>(
-            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -4636,7 +4633,7 @@ namespace System.Linq
         /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TSource> Intersect<TSource>(
-            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             if (first == null) throw new ArgumentNullException(nameof(first));
             if (second == null) throw new ArgumentNullException(nameof(second));
@@ -4662,7 +4659,7 @@ namespace System.Linq
         /// </remarks>
         [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
         public static ParallelQuery<TSource> Intersect<TSource>(
-            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -4732,7 +4729,7 @@ namespace System.Linq
         /// <paramref name="first"/> or <paramref name="second"/> is a null reference (Nothing in Visual Basic).
         /// </exception>
         public static ParallelQuery<TSource> Except<TSource>(
-            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, ParallelQuery<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             if (first == null) throw new ArgumentNullException(nameof(first));
             if (second == null) throw new ArgumentNullException(nameof(second));
@@ -4758,7 +4755,7 @@ namespace System.Linq
         /// </remarks>
         [Obsolete(RIGHT_SOURCE_NOT_PARALLEL_STR)]
         public static ParallelQuery<TSource> Except<TSource>(
-            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+            this ParallelQuery<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource>? comparer)
         {
             throw new NotSupportedException(SR.ParallelEnumerable_BinaryOpMustUseAsParallel);
         }
@@ -4811,9 +4808,7 @@ namespace System.Linq
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
 
-            QueryOperator<TSource> asOperator = source as QueryOperator<TSource>;
-
-            if (asOperator != null)
+            if (source is QueryOperator<TSource> asOperator)
             {
                 return asOperator.ExecuteAndGetResultsAsArray();
             }
@@ -4848,9 +4843,8 @@ namespace System.Linq
             // Allocate a growable list (optionally passing the length as the initial size).
             List<TSource> list = new List<TSource>();
             IEnumerator<TSource> input;
-            QueryOperator<TSource> asOperator = source as QueryOperator<TSource>;
 
-            if (asOperator != null)
+            if (source is QueryOperator<TSource> asOperator)
             {
                 if (asOperator.OrdinalIndexState == OrdinalIndexState.Indexable && asOperator.OutputOrdered)
                 {
@@ -4924,7 +4918,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector) where TKey : notnull
         {
             return ToDictionary(source, keySelector, EqualityComparer<TKey>.Default);
         }
@@ -4953,7 +4947,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) where TKey : notnull
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -4961,7 +4955,7 @@ namespace System.Linq
             // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
             Dictionary<TKey, TSource> result = new Dictionary<TKey, TSource>(comparer);
 
-            QueryOperator<TSource> op = source as QueryOperator<TSource>;
+            QueryOperator<TSource>? op = source as QueryOperator<TSource>;
             IEnumerator<TSource> input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);
 
             using (input)
@@ -5022,7 +5016,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TKey : notnull
         {
             return ToDictionary(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
         }
@@ -5057,7 +5051,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer) where TKey : notnull
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -5066,7 +5060,7 @@ namespace System.Linq
             // comparer may be null. In that case, the Dictionary constructor will use the default comparer.
             Dictionary<TKey, TElement> result = new Dictionary<TKey, TElement>(comparer);
 
-            QueryOperator<TSource> op = source as QueryOperator<TSource>;
+            QueryOperator<TSource>? op = source as QueryOperator<TSource>;
             IEnumerator<TSource> input = (op == null) ? source.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered, true);
 
             using (input)
@@ -5121,7 +5115,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector) where TKey: notnull
         {
             return ToLookup(source, keySelector, EqualityComparer<TKey>.Default);
         }
@@ -5146,7 +5140,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) where TKey: notnull
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -5159,7 +5153,7 @@ namespace System.Linq
             Parallel.Lookup<TKey, TSource> lookup = new Parallel.Lookup<TKey, TSource>(comparer);
 
             Debug.Assert(groupings is QueryOperator<IGrouping<TKey, TSource>>);
-            QueryOperator<IGrouping<TKey, TSource>> op = groupings as QueryOperator<IGrouping<TKey, TSource>>;
+            QueryOperator<IGrouping<TKey, TSource>>? op = groupings as QueryOperator<IGrouping<TKey, TSource>>;
 
             IEnumerator<IGrouping<TKey, TSource>> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
 
@@ -5200,7 +5194,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) where TKey : notnull
         {
             return ToLookup(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
         }
@@ -5232,7 +5226,7 @@ namespace System.Linq
         /// The query was canceled.
         /// </exception>
         public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
-            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+            this ParallelQuery<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey>? comparer) where TKey : notnull
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (keySelector == null) throw new ArgumentNullException(nameof(keySelector));
@@ -5246,7 +5240,7 @@ namespace System.Linq
             Parallel.Lookup<TKey, TElement> lookup = new Parallel.Lookup<TKey, TElement>(comparer);
 
             Debug.Assert(groupings is QueryOperator<IGrouping<TKey, TElement>>);
-            QueryOperator<IGrouping<TKey, TElement>> op = groupings as QueryOperator<IGrouping<TKey, TElement>>;
+            QueryOperator<IGrouping<TKey, TElement>>? op = groupings as QueryOperator<IGrouping<TKey, TElement>>;
 
             IEnumerator<IGrouping<TKey, TElement>> input = (op == null) ? groupings.GetEnumerator() : op.GetEnumerator(ParallelMergeOptions.FullyBuffered);
 
@@ -5338,7 +5332,7 @@ namespace System.Linq
         //     defaultIfEmpty - whether to return a default value (true) or throw an
         //                      exception if the output of the query operator is empty
         //
-
+        [return: MaybeNull]
         private static TSource GetOneWithPossibleDefault<TSource>(
             QueryOperator<TSource> queryOp, bool throwIfTwo, bool defaultIfEmpty)
         {
@@ -5370,7 +5364,7 @@ namespace System.Linq
 
             if (defaultIfEmpty)
             {
-                return default(TSource);
+                return default(TSource)!;
             }
             else
             {
@@ -5422,7 +5416,7 @@ namespace System.Linq
                     .First();
             }
 
-            return GetOneWithPossibleDefault(queryOp, false, false);
+            return GetOneWithPossibleDefault(queryOp, false, false)!;
         }
 
         /// <summary>
@@ -5464,7 +5458,7 @@ namespace System.Linq
                     .First(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
             }
 
-            return GetOneWithPossibleDefault(queryOp, false, false);
+            return GetOneWithPossibleDefault(queryOp, false, false)!;
         }
 
         /// <summary>
@@ -5485,6 +5479,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource FirstOrDefault<TSource>(this ParallelQuery<TSource> source)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -5531,6 +5526,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource FirstOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -5598,7 +5594,7 @@ namespace System.Linq
                 return ExceptionAggregator.WrapEnumerable(childWithCancelChecks, settings.CancellationState).Last();
             }
 
-            return GetOneWithPossibleDefault(queryOp, false, false);
+            return GetOneWithPossibleDefault(queryOp, false, false)!;
         }
 
         /// <summary>
@@ -5642,7 +5638,7 @@ namespace System.Linq
                     .Last(ExceptionAggregator.WrapFunc<TSource, bool>(predicate, settings.CancellationState));
             }
 
-            return GetOneWithPossibleDefault(queryOp, false, false);
+            return GetOneWithPossibleDefault(queryOp, false, false)!;
         }
 
         /// <summary>
@@ -5663,6 +5659,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource LastOrDefault<TSource>(this ParallelQuery<TSource> source)
         {
             // @PERF: optimize for seekable data sources.  E.g. if an array, we can
@@ -5705,6 +5702,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource LastOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -5759,7 +5757,7 @@ namespace System.Linq
             //     check the Count property and avoid costly fork/join/synchronization.
             if (source == null) throw new ArgumentNullException(nameof(source));
 
-            return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, null), true, false);
+            return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, null), true, false)!;
         }
 
         /// <summary>
@@ -5787,7 +5785,7 @@ namespace System.Linq
             if (source == null) throw new ArgumentNullException(nameof(source));
             if (predicate == null) throw new ArgumentNullException(nameof(predicate));
 
-            return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, predicate), true, false);
+            return GetOneWithPossibleDefault(new SingleQueryOperator<TSource>(source, predicate), true, false)!;
         }
 
         /// <summary>
@@ -5809,6 +5807,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource SingleOrDefault<TSource>(this ParallelQuery<TSource> source)
         {
             // @PERF: optimize for ICollection-typed data sources, i.e. we can just
@@ -5839,6 +5838,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource SingleOrDefault<TSource>(this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -5866,7 +5866,7 @@ namespace System.Linq
         /// </exception>
         public static ParallelQuery<TSource> DefaultIfEmpty<TSource>(this ParallelQuery<TSource> source)
         {
-            return DefaultIfEmpty<TSource>(source, default(TSource));
+            return DefaultIfEmpty<TSource>(source, default!);
         }
 
         /// <summary>
@@ -5924,7 +5924,7 @@ namespace System.Linq
             ElementAtQueryOperator<TSource> op = new ElementAtQueryOperator<TSource>(source, index);
 
             TSource result;
-            if (op.Aggregate(out result, false))
+            if (op.Aggregate(out result!, false))
             {
                 return result;
             }
@@ -5952,6 +5952,7 @@ namespace System.Linq
         /// <exception cref="System.OperationCanceledException">
         /// The query was canceled.
         /// </exception>
+        [return: MaybeNull]
         public static TSource ElementAtOrDefault<TSource>(this ParallelQuery<TSource> source, int index)
         {
             if (source == null) throw new ArgumentNullException(nameof(source));
@@ -5964,13 +5965,13 @@ namespace System.Linq
                 ElementAtQueryOperator<TSource> op = new ElementAtQueryOperator<TSource>(source, index);
 
                 TSource result;
-                if (op.Aggregate(out result, true))
+                if (op.Aggregate(out result!, true))
                 {
                     return result;
                 }
             }
 
-            return default(TSource);
+            return default(TSource)!;
         }
     }
 }