dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'selector')

Error message

Value cannot be null. (Parameter 'selector')

What it means

The Case operator picks an IEnumerable<TResult> from a dictionary by invoking the supplied selector function. It eagerly validates arguments and throws ArgumentNullException with parameter name 'selector' when the selector delegate is null, failing fast before any enumeration occurs.

Solutions

  1. Pass a non-null Func<TValue> selector to Case
  2. Check the value-producing code path (config/DI) that yielded a null delegate
  3. Guard with null check before calling Case

Example fix

// before
Func<int> selector = config?.GetSelector(); // may be null
var seq = Case(selector, sources);
// after
var sel = config?.GetSelector() ?? throw new InvalidOperationException("selector not configured");
var seq = Case(sel, sources);
Defensive patterns

Strategy: validation

Validate before calling

if (selector == null) throw new ArgumentException("selector must not be null", nameof(selector));

Type guard

bool IsValidCaseCall<TValue>(Func<TValue> selector) => selector != null;

Try / catch

try { seq = Case(selector, sources); } catch (ArgumentNullException ex) when (ex.ParamName == "selector") { seq = Enumerable.Empty<TResult>(); }

Prevention

When it happens

Trigger: Calling Case<TValue,TResult>(null, sources) with a null selector delegate; also indirectly via the overload with defaultSource and via a null factory in related overloads.

Common situations: Selector supplied from a config-resolved delegate or DI construction that returned null; refactoring left the lambda uninitialized.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Case.cs:22

using System.Collections.Generic;

namespace System.Linq
{
    public static partial class EnumerableEx
    {
        /// <summary>
        /// Returns a sequence from a dictionary based on the result of evaluating a selector function.
        /// </summary>
        /// <typeparam name="TValue">Type of the selector value.</typeparam>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, an empty sequence.</returns>
        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources)
        {
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));
            if (sources == null)
                throw new ArgumentNullException(nameof(sources));

            return Case(selector, sources, []);
        }

        /// <summary>
        /// Returns a sequence from a dictionary based on the result of evaluating a selector function, also specifying a
        /// default sequence.
        /// </summary>
        /// <typeparam name="TValue">Type of the selector value.</typeparam>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
        /// <param name="defaultSource">
        /// Default sequence to return in case there's no corresponding source for the computed
        /// selector value.
        /// </param>

View on GitHub (pinned to 94b5d5ab91)