dotnet/reactive · error · ArgumentNullException

selector

Error message

selector

What it means

The three-argument Case overload throws ArgumentNullException when the selector delegate is null. Case invokes selector per subscription to pick a branch from the sources dictionary, so a null selector cannot be honored and is rejected eagerly at Observable.Imperative.cs:135.

Solutions

  1. Supply a valid Func<TValue> that returns a key present in the dictionary (or one that falls through to defaultSource).
  2. If a default key is appropriate, pass e.g. () => defaultKey instead of null.
  3. Check the injection/factory path that was supposed to produce the selector.

Example fix

// before
Func<string> selector = config.Mode == "custom" ? BuildSelector() : null;
Observable.Case(selector, sources, defaultSrc);
// after
Func<string> selector = config.Mode == "custom" ? BuildSelector() : () => "default";
Observable.Case(selector, sources, defaultSrc);
Defensive patterns

Strategy: validation

Validate before calling

if (selector is null) throw new ArgumentNullException(nameof(selector));
var result = Observable.Case(selector, sources, defaultSource);

Try / catch

try { var q = Observable.Case(selector, sources, defaultSource); }
catch (ArgumentNullException ex) when (ex.ParamName == "selector") { /* rebuild selector from config or use a default-key selector */ }

Prevention

When it happens

Trigger: Calling Observable.Case<TValue,TResult>(selector, sources, defaultSource) with a null Func<TValue>, e.g. when the selector was meant to be built from configuration or injected and was never initialized.

Common situations: Dependency injection wiring misses the selector; a local Func variable assigned only in some branches; factory methods that return null instead of a default delegate.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Imperative.cs:135

        #region + Case +

        /// <summary>
        /// Uses <paramref name="selector"/> to determine which source in <paramref name="sources"/> to return, choosing <paramref name="defaultSource"/> if no match is found.
        /// </summary>
        /// <typeparam name="TValue">The type of the value returned by the selector function, used to look up the resulting source.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence.</typeparam>
        /// <param name="selector">Selector function invoked to determine the source to lookup in the <paramref name="sources"/> dictionary.</param>
        /// <param name="sources">Dictionary of sources to select from based on the <paramref name="selector"/> invocation result.</param>
        /// <param name="defaultSource">Default source to select in case no matching source in <paramref name="sources"/> is found.</param>
        /// <returns>The observable sequence retrieved from the <paramref name="sources"/> dictionary based on the <paramref name="selector"/> invocation result, or <paramref name="defaultSource"/> if no match is found.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="selector"/> or <paramref name="sources"/> or <paramref name="defaultSource"/> is null.</exception>
        public static IObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IObservable<TResult>> sources, IObservable<TResult> defaultSource)
            where TValue : notnull
        {
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            if (sources == null)
            {
                throw new ArgumentNullException(nameof(sources));
            }

            if (defaultSource == null)
            {
                throw new ArgumentNullException(nameof(defaultSource));
            }

            return s_impl.Case(selector, sources, defaultSource);
        }

        /// <summary>
        /// Uses <paramref name="selector"/> to determine which source in <paramref name="sources"/> to return, choosing an empty sequence on the specified scheduler if no match is found.
        /// </summary>

View on GitHub (pinned to 94b5d5ab91)