{"record":{"id":"3c1001b34bee57ed","repo":"stride3d/stride","slug":"expecting-a-type-inheriting-from-system-collections-generic-3c1001","errorCode":null,"errorMessage":"Expecting a type inheriting from System.Collections.Generic.IList<T>","messagePattern":"Expecting a type inheriting from System\\.Collections\\.Generic\\.IList<T>","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Reflection/TypeDescriptors/ListDescriptor.cs","lineNumber":41,"sourceCode":"    private Action<object, int, object?> insertMethod;\n    private Action<object, int> removeAtMethod;\n    private Action<object, object?> removeMethod;\n    private Action<object> clearMethod;\n\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"ListDescriptor\" /> class.\n    /// </summary>\n    /// <param name=\"factory\">The factory.</param>\n    /// <param name=\"type\">The type.</param>\n    /// <exception cref=\"ArgumentException\">Expecting a type inheriting from System.Collections.IList;type</exception>\n#pragma warning disable CS8618\n    // This warning is disabled because the necessary initialization will occur \n    // in the CreateListDelegates<T>() method, not in the constructor.\n    public ListDescriptor(ITypeDescriptorFactory factory, Type type, bool emitDefaultValues, IMemberNamingConvention namingConvention)\n        : base(factory, type, emitDefaultValues, namingConvention)\n    {\n        if (!IsList(type))\n            throw new ArgumentException(@\"Expecting a type inheriting from System.Collections.Generic.IList<T>\", nameof(type));\n\n        HasAdd = true;\n        HasRemove = true;\n        HasInsert = true;\n        HasRemoveAt = true;\n        HasIndexerAccessors = true;\n\n        ElementType = type.GetInterface(typeof(IList<>))!.GetGenericArguments()[0]!;\n\n        // if the type has late bound generics, no delegates can be created as the type is invalid for calling collection operations\n        if (type.ContainsGenericParameters)\n            return;\n\n        var interfaceType = type.GetInterface(typeof(IList<>));\n        var valueType = interfaceType!.GetGenericArguments()[0];\n        var descriptorType = typeof(ListDescriptor).GetMethod(nameof(CreateListDelegates), BindingFlags.NonPublic | BindingFlags.Instance)!.MakeGenericMethod([valueType]);\n        descriptorType.Invoke(this, []);\n    }","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Reflection/TypeDescriptors/ListDescriptor.cs#L23-L59","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use List<T> or any type implementing IList<T>.","Migrate ArrayList/non-generic IList fields to List<T>.","If you own the collection, implement IList<T> on it.","Fix the factory's type selection so list types only produce ListDescriptor."],"exampleFix":"// before\npublic ArrayList Items;\n// after\npublic List<MyItem> Items;","handlingStrategy":"type-guard","validationCode":"if (!ListDescriptor.IsList(type))\n    throw new ArgumentException(\"Type must implement IList<T>\", nameof(type));","typeGuard":"static bool IsGenericList(Type t) => t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));","tryCatchPattern":"try { var d = new ListDescriptor(factory, type, true, naming); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"IList<T>\")) { /* use a generic list type */ }","preventionTips":["Use List<T> (or implement IList<T>) in serialized models.","Replace ArrayList/non-generic IList fields; verify factory routing for collection types."],"tags":["type-mismatch","list","generics"],"backgroundTag":"type-mismatch","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}