dotnet/reactive · error · ArgumentNullException

Thrown when keySelector is null (ArgumentNullException…

Error message

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

What it means

The obsolete MaxBy operator requires a non-null keySelector to extract the comparison key from each element. Passing null throws ArgumentNullException with paramName 'keySelector' immediately at the call site. This overload is deprecated in favor of MaxByWithTies.

Solutions

  1. Supply an explicit key selector lambda, e.g. x => x.Key.
  2. Null-check or default the selector before calling: keySelector ??= x => x;
  3. Prefer migrating to MaxByWithTies, which is the non-obsolete replacement, while fixing the null selector.

Example fix

// before
var best = rows.MaxBy(GetKeySelector()); // returns null when unconfigured
// after
var sel = GetKeySelector() ?? (Row r => r.Id);
var best = rows.MaxByWithTies(sel);
Defensive patterns

Strategy: validation

Validate before calling

if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));
var best = source.MaxBy(keySelector);

Type guard

static Func<T, TKey> RequireSelector<T, TKey>(Func<T, TKey>? sel) => sel ?? throw new ArgumentNullException(nameof(sel));

Try / catch

try
{
    var best = source.MaxBy(keySelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector")
{
    // supply or fix the key selector before retrying
}

Prevention

When it happens

Trigger: Calling source.MaxBy(null), or forwarding a keySelector parameter that is null, e.g. rows.MaxBy(GetSelector()) where GetSelector() returns null.

Common situations: Building query pipelines dynamically where the selector is composed/registered and ends up null; generic helper methods that accept a Func<TSource,TKey> which callers omit.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxBy.cs:26

{
    public static partial class EnumerableEx
    {
#if !(REFERENCE_ASSEMBLY && NET6_0_OR_GREATER)
        /// <summary>
        /// Returns the elements with the maximum key value by using the default comparer to compare key values.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <typeparam name="TKey">Key type.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
        /// <returns>List with the elements that share the same maximum key value.</returns>
        [Obsolete("Use MaxByWithTies to maintain same behavior with .NET 6 and later", false)]
        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));

            return MaxBy(source, keySelector, Comparer<TKey>.Default);
        }

        /// <summary>
        /// Returns the elements with the minimum key value by using the specified comparer to compare key values.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <typeparam name="TKey">Key type.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
        /// <param name="comparer">Comparer used to determine the maximum key value.</param>
        /// <returns>List with the elements that share the same maximum key value.</returns>
        [Obsolete("Use MaxByWithTies to maintain same behavior with .NET 6 and later", false)]
        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

View on GitHub (pinned to 94b5d5ab91)