{"record":{"id":"f4cb910968b7f3c1","repo":"dotnet/reactive","slug":"comparer","errorCode":null,"errorMessage":"comparer","messagePattern":"comparer","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Distinct.cs","lineNumber":24,"sourceCode":"\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TSource> Distinct<TSource>(IAsyncObservable<TSource> source)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n\n            return Create(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.Distinct(observer)));\n        }\n\n        public static IAsyncObservable<TSource> Distinct<TSource>(IAsyncObservable<TSource> source, IEqualityComparer<TSource> comparer)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return Create(\n                source,\n                comparer,\n                static (source, comparer, observer) => source.SubscribeSafeAsync(AsyncObserver.Distinct(observer, comparer)));\n        }\n    }\n\n    public partial class AsyncObserver\n    {\n        public static IAsyncObserver<TSource> Distinct<TSource>(IAsyncObserver<TSource> observer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n\n            return Distinct(observer, EqualityComparer<TSource>.Default);\n        }\n","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Distinct.cs#L6-L42","documentation":"The comparer-taking Distinct overload throws ArgumentNullException when the IEqualityComparer<TSource> argument is null. A comparer is required to decide element uniqueness; there is no null-comparer fallback in this overload (use the single-argument overload for default equality). The check runs before Create is invoked.","triggerScenarios":"Calling source.Distinct(null) with a comparer-typed variable that was never assigned, or a comparer factory returning null.","commonSituations":"DI/config-driven comparer resolution returning null for an unknown key; conditional comparer building that skips assignment; tests passing null to use 'default' behavior incorrectly.","solutions":["Pass a concrete comparer such as EqualityComparer<TSource>.Default.","Use the Distinct(source) overload when you want default equality semantics.","Fix the comparer factory/registration so it never returns null."],"exampleFix":"// before\nsource.Distinct(comparer); // comparer == null\n// after\nsource.Distinct(comparer ?? EqualityComparer<int>.Default);","handlingStrategy":"validation","validationCode":"if (comparer is null) comparer = EqualityComparer<TSource>.Default;\nvar distinct = source.Distinct(comparer);","typeGuard":"bool HasComparer<T>(IEqualityComparer<T>? c) => c is not null;","tryCatchPattern":"try\n{\n    var distinct = source.Distinct(comparer);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"comparer\")\n{\n    logger.LogError(ex, \"Distinct called with null comparer\");\n    var distinct = source.Distinct();\n}","preventionTips":["Default comparer fields to EqualityComparer<T>.Default at declaration.","Make comparer factories throw instead of returning null on unknown keys.","Use the single-argument Distinct overload when default equality suffices."],"tags":["argument-null","async-rx","comparer","fail-fast"],"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"}