stride3d/stride · error · ArgumentException

Expecting a type inheriting from…

Error message

Expecting a type inheriting from System.Collections.Generic.IList<T>

What it means

ListDescriptor requires the type to implement the generic IList<T> interface (checked by its IsList helper). Passing a type that is not a generic list — e.g. ArrayList, non-generic IList, or an unrelated class — makes the constructor throw ArgumentException.

Solutions

  1. Use List<T> or any type implementing IList<T>.
  2. Migrate ArrayList/non-generic IList fields to List<T>.
  3. If you own the collection, implement IList<T> on it.
  4. Fix the factory's type selection so list types only produce ListDescriptor.

Example fix

// before
public ArrayList Items;
// after
public List<MyItem> Items;
Defensive patterns

Strategy: type-guard

Validate before calling

if (!ListDescriptor.IsList(type))
    throw new ArgumentException("Type must implement IList<T>", nameof(type));

Type guard

static bool IsGenericList(Type t) => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));

Try / catch

try { var d = new ListDescriptor(factory, type, true, naming); }
catch (ArgumentException ex) when (ex.Message.Contains("IList<T>")) { /* use a generic list type */ }

Prevention

When it happens

Trigger: new ListDescriptor(factory, typeof(ArrayList), ...) or typeof(System.Collections.IList) (non-generic) or any non-list type; a custom collection that only implements the non-generic IList.

Common situations: Legacy collections using ArrayList or non-generic IList in models meant for Stride serialization; a custom list type missing the generic IList<T> implementation; mis-routing non-list types to ListDescriptor in a custom factory.

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/3c1001b34bee57ed. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Reflection/TypeDescriptors/ListDescriptor.cs:41

    private Action<object, int, object?> insertMethod;
    private Action<object, int> removeAtMethod;
    private Action<object, object?> removeMethod;
    private Action<object> clearMethod;

    /// <summary>
    /// Initializes a new instance of the <see cref="ListDescriptor" /> class.
    /// </summary>
    /// <param name="factory">The factory.</param>
    /// <param name="type">The type.</param>
    /// <exception cref="ArgumentException">Expecting a type inheriting from System.Collections.IList;type</exception>
#pragma warning disable CS8618
    // This warning is disabled because the necessary initialization will occur 
    // in the CreateListDelegates<T>() method, not in the constructor.
    public ListDescriptor(ITypeDescriptorFactory factory, Type type, bool emitDefaultValues, IMemberNamingConvention namingConvention)
        : base(factory, type, emitDefaultValues, namingConvention)
    {
        if (!IsList(type))
            throw new ArgumentException(@"Expecting a type inheriting from System.Collections.Generic.IList<T>", nameof(type));

        HasAdd = true;
        HasRemove = true;
        HasInsert = true;
        HasRemoveAt = true;
        HasIndexerAccessors = true;

        ElementType = type.GetInterface(typeof(IList<>))!.GetGenericArguments()[0]!;

        // 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 interfaceType = type.GetInterface(typeof(IList<>));
        var valueType = interfaceType!.GetGenericArguments()[0];
        var descriptorType = typeof(ListDescriptor).GetMethod(nameof(CreateListDelegates), BindingFlags.NonPublic | BindingFlags.Instance)!.MakeGenericMethod([valueType]);
        descriptorType.Invoke(this, []);
    }

View on GitHub (pinned to 96fad776d2)