PrismLibrary/Prism · error · InvalidCastException

Resources.DelegateCommandInvalidGenericPayloadType

Error message

Resources.DelegateCommandInvalidGenericPayloadType

What it means

DelegateCommand<T> only supports payload types that are reference types or nullable value types. The constructor inspects the generic type argument at runtime and throws InvalidCastException if T is a non-nullable value type, because the underlying execute/canExecute delegates cannot be invoked with such payloads.

Solutions

  1. Change the generic parameter to the nullable form, e.g. DelegateCommand<int?>
  2. Use the object payload form DelegateCommand<object> and cast inside the execute method
  3. Use a reference-type wrapper (class) for the payload instead of a struct

Example fix

// before
public DelegateCommand<int> SelectItemCommand { get; }
// after
public DelegateCommand<int?> SelectItemCommand { get; }
Defensive patterns

Strategy: validation

Validate before calling

bool payloadOk = !typeof(T).IsValueType || Nullable.GetUnderlyingType(typeof(T)) != null;
if (!payloadOk) throw new InvalidOperationException($"{typeof(T)} must be a reference type or Nullable<>");

Type guard

static bool IsValidDelegateCommandPayload<T>() => !typeof(T).IsValueType || Nullable.GetUnderlyingType(typeof(T)) != null;

Try / catch

try { cmd = new DelegateCommand<T>(execute, canExecute); }
catch (InvalidCastException) { cmd = new DelegateCommand<object>(o => execute((T)o), canExecute); }

Prevention

When it happens

Trigger: Declaring DelegateCommand<int>, DelegateCommand<DateTime>, or any DelegateCommand<TValue> where TValue is a struct that is not Nullable<U>; the exception is thrown from the DelegateCommand constructor.

Common situations: Developers migrating from parameterless commands try to bind commands to value-type command parameters (e.g. an int id) as in WPF's RoutedCommand; Prism's DelegateCommand does not allow it.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/b0718fa4e2eef496. Report an issue: GitHub.

Appendix: source

Thrown at src/Prism.Core/Commands/DelegateCommand{T}.cs:70

        /// </summary>
        /// <param name="executeMethod">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
        /// <param name="canExecuteMethod">Delegate to execute when CanExecute is called on the command. This can be null.</param>
        /// <exception cref="ArgumentNullException">When both <paramref name="executeMethod"/> and <paramref name="canExecuteMethod"/> are <see langword="null" />.</exception>
        public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
            : base()
        {
            if (executeMethod == null || canExecuteMethod == null)
                throw new ArgumentNullException(nameof(executeMethod), Resources.DelegateCommandDelegatesCannotBeNull);

            TypeInfo genericTypeInfo = typeof(T).GetTypeInfo();

            // DelegateCommand allows object or Nullable<>.  
            // note: Nullable<> is a struct so we cannot use a class constraint.
            if (genericTypeInfo.IsValueType)
            {
                if ((!genericTypeInfo.IsGenericType) || (!typeof(Nullable<>).GetTypeInfo().IsAssignableFrom(genericTypeInfo.GetGenericTypeDefinition().GetTypeInfo())))
                {
                    throw new InvalidCastException(Resources.DelegateCommandInvalidGenericPayloadType);
                }
            }

            _executeMethod = executeMethod;
            _canExecuteMethod = canExecuteMethod;
        }

        ///<summary>
        ///Executes the command and invokes the <see cref="Action{T}"/> provided during construction.
        ///</summary>
        ///<param name="parameter">Data used by the command.</param>
        public void Execute(T parameter)
        {
            try
            {
                _executeMethod(parameter);
            }
            catch (Exception ex)

View on GitHub (pinned to 358118cd64)