{"record":{"id":"21a16565e6be70a8","repo":"dotnet/reactive","slug":"thrown-when-comparer-is-null-argumentnullexception-param-21a165","errorCode":null,"errorMessage":"Thrown when comparer is null (ArgumentNullException, param name: comparer)","messagePattern":"Thrown when comparer is null \\(ArgumentNullException, param name: comparer\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxByWithTies.cs","lineNumber":45,"sourceCode":"        }\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        public static IList<TSource> MaxByWithTies<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue));\n        }\n\n        private static IList<TSource> ExtremaBy<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare)\n        {\n            var result = new List<TSource>();\n\n            using (var e = source.GetEnumerator())\n            {\n                if (!e.MoveNext())\n                    throw new InvalidOperationException(\"Source sequence doesn't contain any elements.\");\n\n                var current = e.Current;\n                var resKey = keySelector(current);\n                result.Add(current);\n\n                while (e.MoveNext())","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Ix.NET/Source/System.Interactive/System/Linq/Operators/MaxByWithTies.cs#L27-L63","documentation":"The comparer-overload MaxByWithTies(source, keySelector, comparer) throws ArgumentNullException with param name 'comparer' when the IComparer<TKey> is null. Unlike Comparer<TKey>.Default used by the two-argument overload, the explicit comparer must be provided.","triggerScenarios":"Passing a null IComparer<TKey> in the three-argument overload, e.g. items.MaxByWithTies(x => x.Key, null), commonly when the comparer is fetched from a registry or constructed conditionally.","commonSituations":"Comparer obtained from a dictionary/config that returned null; a custom comparer class whose factory failed; using null intending 'default' semantics.","solutions":["Pass Comparer<TKey>.Default instead of null when default comparison is desired","Null-check the comparer before the call and fall back to Comparer<TKey>.Default","Fix the factory/lookup that produced the null comparer"],"exampleFix":"// before\nitems.MaxByWithTies(x => x.Score, null);\n// after\nitems.MaxByWithTies(x => x.Score, scoreComparer ?? Comparer<int>.Default);","handlingStrategy":"validation","validationCode":"if (comparer is null) comparer = Comparer<TKey>.Default;\nvar ties = source.MaxByWithTies(keySelector, comparer);","typeGuard":"static IComparer<T> OrDefault<T>(IComparer<T>? c) => c ?? Comparer<T>.Default;","tryCatchPattern":"try { result = source.MaxByWithTies(sel, cmp); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"comparer\") { result = source.MaxByWithTies(sel); }","preventionTips":["Use Comparer<T>.Default instead of null to mean 'default comparison'","Validate comparer factories/registries return non-null","Coalesce comparer arguments at the pipeline boundary"],"tags":["csharp","null-argument","icomparer","linq"],"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"}