{"record":{"id":"2a100ddda809d3af","repo":"stride3d/stride","slug":"the-generic-argument-of-this-class-must-be-the-type-being","errorCode":null,"errorMessage":"The generic argument of this class must be the type being implemented.","messagePattern":"The generic argument of this class must be the type being implemented\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Wpf/ValueConverters/MultiValueConverterBase.cs","lineNumber":24,"sourceCode":"using System.Windows.Markup;\n\nnamespace Stride.Core.Presentation.ValueConverters\n{\n    /// <summary>\n    /// An abstract class for implementations of <see cref=\"IMultiValueConverter\"/> that supports markup extensions.\n    /// </summary>\n    /// <typeparam name=\"T\">The type of <see cref=\"IValueConverter\"/> being implemented.</typeparam>\n    public abstract class MultiValueConverterBase<T> : MarkupExtension, IMultiValueConverter where T : class, IMultiValueConverter, new()\n    {\n        private static T valueConverterInstance;\n\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"ValueConverterBase{T}\"/> class.\n        /// </summary>\n        /// <exception cref=\"InvalidOperationException\">The generic argument does not match the type of the implementation of this class.</exception>\n        protected MultiValueConverterBase()\n        {\n            if (GetType() != typeof(T)) throw new InvalidOperationException(\"The generic argument of this class must be the type being implemented.\");\n        }\n\n        /// <inheritdoc/>\n        public override object ProvideValue(IServiceProvider serviceProvider)\n        {\n            return valueConverterInstance ?? (valueConverterInstance = new T());\n        }\n\n        /// <inheritdoc/>\n        public abstract object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);\n\n        /// <inheritdoc/>\n        public abstract object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);\n    }\n}\n","sourceCodeStart":6,"sourceCodeEnd":40,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/ValueConverters/MultiValueConverterBase.cs#L6-L40","documentation":"MultiValueConverterBase<T> requires that the concrete class deriving from it is exactly T. This enables ProvideValue to return a new T() instance from XAML markup extension usage. If GetType() != typeof(T), the generic parameter doesn't match the implementation, and the constructor throws InvalidOperationException.","triggerScenarios":"Declaring class Foo : MultiValueConverterBase<Bar> where Bar is not Foo; copy-pasting a converter class and updating only the base type's generic argument; renaming a class without updating the generic parameter.","commonSituations":"Copy-paste errors when creating new converters; refactoring where the class was renamed but the generic argument still refers to the old name; accidental inheritance hierarchies (subclassing an existing converter without fixing T).","solutions":["Make the generic argument match the class itself: class Foo : MultiValueConverterBase<Foo>.","If a subclass is intended, switch to inheriting the concrete base converter class instead of MultiValueConverterBase.","If no markup-extension instantiation is needed, inherit from a simpler base without the T self-check."],"exampleFix":"// before\nclass MyConverter : MultiValueConverterBase<OtherConverter> { ... }\n// after\nclass MyConverter : MultiValueConverterBase<MyConverter> { ... }","handlingStrategy":"validation","validationCode":"// C# - compile-time self-check pattern\n// class MyConverter : MultiValueConverterBase<MyConverter> { }  // T must equal the class name","typeGuard":null,"tryCatchPattern":"try { var c = new MyConverter(); } catch (InvalidOperationException ex) { /* generic argument mismatch */ }","preventionTips":["Always write MultiValueConverterBase<ThisClassName>","Update the generic argument when renaming a converter class","Avoid subclassing concrete converters through MultiValueConverterBase indirectly"],"tags":["wpf","generics","value-converter","invalid-operation"],"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"}