C #универсальный подстановочный знак или как хранить ссылку на неизвестное универсальное наследование

Хорошо, так вот ситуация. У меня есть класс 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>'

Есть ли способ избежать такого столкновения типов?

15
задан AakashM 28 June 2012 в 08:07
поделиться