dotnet/reactive · error · ArgumentNullException
comparer
Error message
comparer
What it means
ArgumentNullException thrown synchronously by the DistinctUntilChanged(source, comparer) overload when the IEqualityComparer<TSource> argument is null. The comparer is required because the operator must compare consecutive elements; there is no default-fallback in this overload (use the single-argument overload for default comparison).
Solutions
- Pass a real comparer, e.g. EqualityComparer<TSource>.Default
- Use the comparer-less overload DistinctUntilChanged(source) when default equality is intended
- Fix the comparer factory/lookup returning null
Example fix
// before var result = source.DistinctUntilChanged(comparer); // comparer may be null // after var result = source.DistinctUntilChanged(comparer ?? EqualityComparer<MyType>.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (comparer is null) comparer = EqualityComparer<TSource>.Default;
Type guard
static bool HasComparer<T>(IEqualityComparer<T>? c) => c is not null;
Try / catch
try { var r = source.DistinctUntilChanged(cmp); }
catch (ArgumentNullException ex) when (ex.ParamName == "comparer") { /* fall back to default comparer */ } Prevention
- Default comparer variables to EqualityComparer<T>.Default at declaration
- Avoid conditional comparer assignment that can leave the variable null
- Register comparers in DI before pipelines consume them
When it happens
Trigger: Calling DistinctUntilChanged(source, null) explicitly, or passing a comparer variable/field that was never assigned, or a factory method that returned null for the comparer.
Common situations: Conditional comparer selection where the else-branch leaves the variable null; DI-resolved comparers not registered; config-driven comparer lookup miss.
Related errors
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'onNext')
- Value cannot be null. (Parameter 'onError')
- Value cannot be null. (Parameter 'func')
- Value cannot be null. (Parameter 'resultSelector')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/fb6abff26141b130.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/DistinctUntilChanged.cs:25
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> DistinctUntilChanged<TSource>(IAsyncObservable<TSource> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return Create(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer)));
}
public static IAsyncObservable<TSource> DistinctUntilChanged<TSource>(IAsyncObservable<TSource> source, IEqualityComparer<TSource> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return Create(
source,
comparer,
static (source, comparer, observer) => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, comparer)));
}
public static IAsyncObservable<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
return Create(
source,
keySelector,
static (source, keySelector, observer) => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, keySelector)));View on GitHub (pinned to 94b5d5ab91)