Хорошо, так вот ситуация. У меня есть класс FlexCollection<T>
, целью которого является хранение списка некоторой специализации FlexItem
, поэтому:
public class FlexCollection<T> where T : FlexItem, new()
{
public void Add(T item) {... }
...
}
FlexItem
не является родовым классом. Чего я хотел добиться, так это возможности хранить в поле FlexItem
ссылку на коллекцию, содержащую объект. К сожалению, в C #невозможно сохранить ссылку на "любую" специализацию шаблонного класса (, как в Java ). Сначала я пытался использовать не -общий интерфейс IFlexCollection
, но на самом деле это вынуждало меня реализовывать каждый метод дважды, т.е.:
public class FlexCollection<T> : IFlexCollection where T : FlexItem, new()
{
public void Add(T item) {... } // to use in generic calls
public void Add(object item) {... } // to use for calls from within FlexItem
...
}
Затем я обнаружил, что сам могу сделать FlexItem универсальным классом! Тогда специализация может содержать ссылку на коллекцию объектов этой специализации (, что вполне логично ). Поэтому:
public class FlexItem<T> where T : FlexItem<T>, new()
{
public FlexCollection<T> ReferenceToParentCollection;
...
}
public class FlexCollection<T> where T : FlexItem<T>, new()
{
public void Add(T item) {... }
...
}
Теперь я могу объявить некоторую FlexItem<T>
специализацию и соответствующую коллекцию:
public class BasicItem : FlexItem<BasicItem> { public int A; }
public class BasicCollection : FlexCollection<BasicItem> { };
Проблема возникает, когда я пытаюсь расширить эти классы для хранения дополнительных полей. т.е. Мне нужен класс ExtendedItem
, который содержит поле B
в дополнение к полю A
:
public class ExtendedItem : BasicItem { public int B; }
public class ExtendedCollection : FlexCollection<ExtendedItem> { };
. А дело в том, что ExtendedItem
является подклассом FlexItem<BasicItem>
, а не FlexItem<ExtendedItem>
. Поэтому невозможно объявить ExtendedCollection
как указано выше. Это вызывает ошибку компиляции:
The type 'Demo.ExtendedItem' must be convertible to
'Demo.FlexItem<Demo.ExtendedItem>' in order to use it as parameter 'T'
in the generic type or method 'Demo.BasicCollection<T>'
Есть ли способ избежать такого столкновения типов?