{"record":{"id":"9703f140dbc41c74","repo":"dotnet/reactive","slug":"thrown-when-keyselector-is-null-argumentnullexception-param","errorCode":null,"errorMessage":"Thrown when keySelector is null (ArgumentNullException, param name: keySelector)","messagePattern":"Thrown when keySelector is null \\(ArgumentNullException, param name: keySelector\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxBy.cs","lineNumber":26,"sourceCode":"{\n    public static partial class EnumerableEx\n    {\n#if !(REFERENCE_ASSEMBLY && NET6_0_OR_GREATER)\n        /// <summary>\n        /// Returns the elements with the maximum key value by using the default comparer to compare key values.\n        /// </summary>\n        /// <typeparam name=\"TSource\">Source sequence element type.</typeparam>\n        /// <typeparam name=\"TKey\">Key type.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"keySelector\">Key selector used to extract the key for each element in the sequence.</param>\n        /// <returns>List with the elements that share the same maximum key value.</returns>\n        [Obsolete(\"Use MaxByWithTies to maintain same behavior with .NET 6 and later\", false)]\n        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n\n            return MaxBy(source, keySelector, Comparer<TKey>.Default);\n        }\n\n        /// <summary>\n        /// Returns the elements with the minimum key value by using the specified comparer to compare key values.\n        /// </summary>\n        /// <typeparam name=\"TSource\">Source sequence element type.</typeparam>\n        /// <typeparam name=\"TKey\">Key type.</typeparam>\n        /// <param name=\"source\">Source sequence.</param>\n        /// <param name=\"keySelector\">Key selector used to extract the key for each element in the sequence.</param>\n        /// <param name=\"comparer\">Comparer used to determine the maximum key value.</param>\n        /// <returns>List with the elements that share the same maximum key value.</returns>\n        [Obsolete(\"Use MaxByWithTies to maintain same behavior with .NET 6 and later\", false)]\n        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxBy.cs#L8-L44","documentation":"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.","triggerScenarios":"Calling source.MaxBy(null), or forwarding a keySelector parameter that is null, e.g. rows.MaxBy(GetSelector()) where GetSelector() returns null.","commonSituations":"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.","solutions":["Supply an explicit key selector lambda, e.g. x => x.Key.","Null-check or default the selector before calling: keySelector ??= x => x;","Prefer migrating to MaxByWithTies, which is the non-obsolete replacement, while fixing the null selector."],"exampleFix":"// before\nvar best = rows.MaxBy(GetKeySelector()); // returns null when unconfigured\n// after\nvar sel = GetKeySelector() ?? (Row r => r.Id);\nvar best = rows.MaxByWithTies(sel);","handlingStrategy":"validation","validationCode":"if (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\nvar best = source.MaxBy(keySelector);","typeGuard":"static Func<T, TKey> RequireSelector<T, TKey>(Func<T, TKey>? sel) => sel ?? throw new ArgumentNullException(nameof(sel));","tryCatchPattern":"try\n{\n    var best = source.MaxBy(keySelector);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"keySelector\")\n{\n    // supply or fix the key selector before retrying\n}","preventionTips":["Always pass an explicit lambda for keySelector; avoid optional Func parameters defaulting to null","Validate composed/dynamic selectors before use","Prefer MaxByWithTies over the obsolete MaxBy"],"tags":["argumentnull","linq","dotnet","ix-net","keyselector","obsolete-api"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}