У меня есть приложение, состоящее из нескольких «уровней» элементов. Некоторые элементы являются родительскими для 0..N дочерних элементов, а сами являются родительскими для 0..N других элементов. Тип верхнего уровня не имеет родителя, а элементы нижнего уровня не имеют потомков.
Другими словами, пусть три типа: A, B и C. Экземпляр A является родителем нескольких экземпляров B, которые сами являются родителями нескольких экземпляров C. Каждый экземпляр также имеет (строго типизированную) ссылку на своего родителя. .
У меня есть несколько методов, которые одинаковы в родительских классах, например AddChild, RemoveChild, GetChildIndex и т. Д. Я хотел бы иметь базовый класс для всех родительских классов, чтобы не дублировать эти методы для каждого родительского типа.
Идея состоит в том, что при наследовании от родительского базового класса вы должны указать тип дочерних элементов в зависимости от типа родительского класса.
Пока что я придумал этот слишком сложный дизайн:
public interface IChild<TParent> where TParent : ParentBase<IChild<TParent>>
{
TParent Parent { get; set; }
}
public class ParentBase<TChild> where TChild : IChild<ParentBase<TChild>>
{
public List<TChild> Children;
}
public class A : ParentBase<B>
{
}
public class B : ParentBase<C>, IChild<A>
{
}
public class C : IChild<B>
{
}
Но я получаю ошибки компиляции:
Error CS0311 The type 'TemplateTest.IChild<TParent>' cannot be used as type parameter 'TChild' in the generic type or method 'ParentBase<TChild>'. There is no implicit reference conversion from 'TemplateTest.IChild<TParent>' to 'TemplateTest.IChild<TemplateTest.ParentBase<TemplateTest.IChild<TParent>>>'. Kbd2 C:\dev\Kbd2\TemplateTest.cs 6 Active
Error CS0311 The type 'TemplateTest.ParentBase<TChild>' cannot be used as type parameter 'TParent' in the generic type or method 'IChild<TParent>'. There is no implicit reference conversion from 'TemplateTest.ParentBase<TChild>' to 'TemplateTest.ParentBase<TemplateTest.IChild<TemplateTest.ParentBase<TChild>>>'. Kbd2 C:\dev\Kbd2\TemplateTest.cs 11 Active
Error CS0311 The type 'TemplateTest.B' cannot be used as type parameter 'TChild' in the generic type or method 'ParentBase<TChild>'. There is no implicit reference conversion from 'TemplateTest.B' to 'TemplateTest.IChild<TemplateTest.ParentBase<TemplateTest.B>>'. Kbd2 C:\dev\Kbd2\TemplateTest.cs 16 Active
Error CS0311 The type 'TemplateTest.C' cannot be used as type parameter 'TChild' in the generic type or method 'ParentBase<TChild>'. There is no implicit reference conversion from 'TemplateTest.C' to 'TemplateTest.IChild<TemplateTest.ParentBase<TemplateTest.C>>'. Kbd2 C:\dev\Kbd2\TemplateTest.cs 20 Active
Error CS1721 Class 'B' cannot have multiple base classes: 'ParentBase<C>' and 'IChild<A>' Kbd2 C:\dev\Kbd2\TemplateTest.cs 20 Active
Error CS0311 The type 'TemplateTest.B' cannot be used as type parameter 'TParent' in the generic type or method 'IChild<TParent>'. There is no implicit reference conversion from 'TemplateTest.B' to 'TemplateTest.ParentBase<TemplateTest.IChild<TemplateTest.B>>'. Kbd2 C:\dev\Kbd2\TemplateTest.cs 24 Active
Я даже не уверен, можно ли это скомпилировать, поскольку классы зависят друг от друга. Я делаю что-то неправильно ? Спасибо.
ИЗМЕНИТЬ: добавлены нереализованные методы и обновлен список ошибок.
EDIT: упростил пример, сделав дочерний интерфейс базовым классом, а не интерфейсом, как и родительский класс.
EDIT: на самом деле разрешен только один базовый класс, поэтому я снова превратил дочерний тип в интерфейс, а не в класс.
ИЗМЕНИТЬ: если я удалю одно из двух ограничений «где», все ошибки исчезнут. Потому что они зависят друг от друга?