C# - как создать унаследованную универсальную коллекцию из фабричного метода
Я пытаюсь написать фабричный метод, который создаст производный экземпляр абстрактного универсального класса коллекции. Вот базовые классы...
abstract class ItemBase { }
abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }
... и их производные классы...
class Item : ItemBase { }
class ItemCollection : CollectionBase<Item> {}
Теперь я хочу фабричный метод, который создаст ItemCollection. Но обратите внимание, что производные классы Item и ItemCollection неизвестны классу, который содержит этот фабричный метод. Вот как я себе это представляю...
static T CreateItemCollection<T>() where T : CollectionBase<ItemBase>, new()
{
return new T();
}
... и я представляю, что вызываю это таким образом...
var collection = CreateItemCollection<ItemCollection>();
Но фабричный метод не будет компилироваться, потому что ItemBase должен иметь конструктор без параметров. И вызов вызова отказывается верить, что ItemCollection
происходит от CollectionBase<ItemBase>
,
Может кто-нибудь, пожалуйста, укажите мне в правильном направлении? Благодарю.
2 ответа
ItemCollection
не выводится из CollectionBase<ItemBase>
, из-за общей инвариантности. В конце концов, вы можете добавить ItemBase
к CollectionBase<ItemBase>
- но ты не хочешь этого для своего ItemCollection
!
Вам нужно сделать метод универсальным для двух параметров типа:
static T CreateItemCollection<TCollection, TItem>()
where TCollection : CollectionBase<TItem>, new()
where TItem : ItemBase
{
return new TCollection();
}
Только тип коллекции нуждается в конструкторе без параметров. Вы бы назвали это с:
var collection = CreateItemCollection<ItemCollection, Item>();
Проблема здесь заключается в том, что в C# 3.0 общие ограничения имеют какую-либо свободу в отношении дисперсии. Соответствие вместо этого довольно строгое. Поскольку ItemCollection происходит от CollectionBase<Item>
он не считается производным от CollectionBase<ItemBase>
даже если типы могут казаться совместимыми.