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> даже если типы могут казаться совместимыми.

Другие вопросы по тегам