stride3d/stride · error · ArgumentException

Expecting a type inheriting from…

Error message

Expecting a type inheriting from System.Collections.Generic.IDictionary<T,K>

What it means

DictionaryDescriptor requires the supplied type to implement the generic IDictionary<TKey,TValue> interface (checked by its IsDictionary helper). If the type is not a generic dictionary — e.g. a Hashtable, non-generic IDictionary, or a plain class — the constructor throws ArgumentException.

Solutions

  1. Use System.Collections.Generic.Dictionary<TKey,TValue> or any type implementing IDictionary<TKey,TValue>.
  2. Migrate non-generic IDictionary/Hashtable fields to generic dictionaries.
  3. If you own the collection type, add IDictionary<TKey,TValue> to its interfaces.
  4. Route truly non-dictionary types to the appropriate descriptor (ListDescriptor, ObjectDescriptor) via the factory.

Example fix

// before
public Hashtable Settings;
// after
public Dictionary<string, object> Settings;
Defensive patterns

Strategy: type-guard

Validate before calling

if (!DictionaryDescriptor.IsDictionary(type))
    throw new ArgumentException("Type must implement IDictionary<TKey,TValue>", nameof(type));

Type guard

static bool IsGenericDictionary(Type t) => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>));

Try / catch

try { var d = new DictionaryDescriptor(factory, type, true, naming); }
catch (ArgumentException ex) when (ex.Message.Contains("IDictionary")) { /* use a generic dictionary type */ }

Prevention

When it happens

Trigger: new DictionaryDescriptor(factory, typeof(Hashtable), ...) or typeof(IDictionary) (non-generic) or any non-dictionary type; passing a custom collection that only implements IDictionary (non-generic).

Common situations: See trigger scenarios.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/b14ebde569fbd91b. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/DictionaryDescriptor.cs:34

    Action<object, object, object?> addMethod;
    Action<object, object> removeMethod;
    Action<object, object, object?> setValueMethod;
    Func<object, object, bool> containsKeyMethod;
    Func<object, ICollection> getKeysMethod;
    Func<object, ICollection> getValuesMethod;
    Func<object, object, object?> getValueMethod;
    Func<object, IEnumerable<KeyValuePair<object, object?>>> getEnumeratorMethod;
    Action<object> clearMethod;

    #pragma warning disable CS8618
    // This warning is disabled because the necessary initialization will occur 
    // in the CreateDictionaryDelegates<T>() method, not in the constructor.
    public DictionaryDescriptor(ITypeDescriptorFactory factory, Type type, bool emitDefaultValues, IMemberNamingConvention namingConvention)
        : base(factory, type, emitDefaultValues, namingConvention)
    {
        if (!IsDictionary(type))
            throw new ArgumentException(@"Expecting a type inheriting from System.Collections.Generic.IDictionary<T,K>", nameof(type));

        // extract Key, Value types from IDictionary<??, ??>
        var interfaceType = type.GetInterface(typeof(IDictionary<,>))!;
        KeyType = interfaceType.GetGenericArguments()[0];
        ValueType = interfaceType.GetGenericArguments()[1];
        IsGenericDictionary = true;

        // if the type has late bound generics, no delegates can be created as the type is invalid for calling collection operations
        if (type.ContainsGenericParameters)
            return;

        var createMethod = typeof(DictionaryDescriptor).GetMethod(nameof(CreateDictionaryDelegates), BindingFlags.NonPublic | BindingFlags.Instance);
        var genericCreateMethod = createMethod!.MakeGenericMethod([KeyType, ValueType]);
        genericCreateMethod!.Invoke(this, []);
    }
    void CreateDictionaryDelegates<TKey, TValue>()
    {
        addMethod = (dictionary, key, value) => ((IDictionary<TKey, TValue?>)dictionary).Add((TKey)key, (TValue?)value);

View on GitHub (pinned to 96fad776d2)