dotnet/reactive · error · ArgumentNullException

Thrown when source is null (ArgumentNullException, param…

Error message

Thrown when source is null (ArgumentNullException, param name: source)

What it means

The comparer-based Max operator finds the maximum element using a caller-supplied IComparer<TSource>. It validates arguments eagerly: a null source throws ArgumentNullException with paramName 'source' before any comparison work begins.

Solutions

  1. Ensure the source collection is initialized before calling Max; check for null and handle the empty/absent case explicitly.
  2. Coalesce: (values ?? throw new InvalidOperationException("no values")).Max(comparer).
  3. Restructure the producer to return an empty sequence; note Max on an empty source will then throw InvalidOperationException (no elements), so handle emptiness separately.

Example fix

// before
var max = readings.Max(tempComparer); // readings null on failed read
// after
var max = readings is null ? throw new InvalidOperationException("no readings") : readings.Max(tempComparer);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new InvalidOperationException("no data to take Max of");
if (comparer is null) comparer = Comparer<TSource>.Default;
var max = source.Max(comparer);

Type guard

static bool CanComputeMax<T>(IEnumerable<T>? source, IComparer<T>? comparer) => source is not null && comparer is not null;

Try / catch

try
{
    var max = source.Max(comparer);
}
catch (ArgumentNullException ex) when (ex.ParamName is "source" or "comparer")
{
    // handle missing source or comparer
}

Prevention

When it happens

Trigger: Calling source.Max(comparer) (IEnumerable<TSource> + IComparer<TSource> overload) with source == null, e.g. values.Max(customComparer) where values is an uninitialized or null-returning collection.

Common situations: Passing results of nullable-returning parsers directly into Max; comparing sequences built conditionally where one branch leaves the variable null; the comparer overload (behind #if for newer TFMs) invoked instead of the parameterless Max.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/2878358f3889744a. Report an issue: GitHub.

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Max.cs:23

using System.Collections.Generic;

namespace System.Linq
{
    public static partial class EnumerableEx
    {

#if !(REFERENCE_ASSEMBLY && NET6_0_OR_GREATER)
        /// <summary>
        /// Returns the maximum value in the enumerable sequence by using the specified comparer to compare values.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="comparer">Comparer used to determine the maximum value.</param>
        /// <returns>Maximum value in the sequence.</returns>
        public static TSource Max<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return MaxByWithTies(source, x => x, comparer).First();
        }
#endif
    }
}

View on GitHub (pinned to 94b5d5ab91)