简体   繁体   English

C# - 如何从工厂方法创建继承的泛型集合

[英]C# - how to create an inherited generic collection from a factory method

I am trying to write a factory method that will create a derived instance of an abstract generic collection class. 我正在尝试编写一个工厂方法,该方法将创建抽象泛型集合类的派生实例。 Here are the base classes ... 这是基类......

abstract class ItemBase { }

abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

...and their derived classes ... ......及其派生类......

class Item : ItemBase { }

class ItemCollection : CollectionBase<Item> {}

Now, I want a factory method that will create an ItemCollection. 现在,我想要一个将创建ItemCollection的工厂方法。 But note that the derived classes Item and ItemCollection are unknown to the class that contains this factory method. 但请注意,派生类Item和ItemCollection对于包含此工厂方法的类是未知的。 This is how I imagine it should be ... 这就是我想象的应该......

static T CreateItemCollection<T>() where T : CollectionBase<ItemBase>, new()
{
    return new T();
}

... and I imagine invoking it thus ... ......我想像这样调用它......

var collection = CreateItemCollection<ItemCollection>();

But the factory method won't compile because ItemBase must have a parameterless constructor. 但是工厂方法不会编译,因为ItemBase必须具有无参数构造函数。 And the invokation call refuses to believe that ItemCollection is derived from CollectionBase<ItemBase> . 并且invokation调用拒绝相信ItemCollection是从CollectionBase<ItemBase>派生的。

Can someone please point me in the right direction? 有人可以指点我正确的方向吗? Thanks. 谢谢。

ItemCollection isn't derived from CollectionBase<ItemBase> , due to generic invariance. 由于泛型不变性, ItemCollection 不是CollectionBase<ItemBase>派生的。 After all, you can add an ItemBase to a CollectionBase<ItemBase> - but you don't want that for your ItemCollection ! 毕竟,您可以将ItemBase添加到CollectionBase<ItemBase> - 但您不希望ItemCollection

You need to make the method generic in two type parameters: 您需要在两个类型参数中使方法通用:

static T CreateItemCollection<TCollection, TItem>()
    where TCollection : CollectionBase<TItem>, new()
    where TItem : ItemBase
{
    return new TCollection();
}

Only the collection type needs a parameterless constructor. 只有集合类型需要无参数构造函数。 You'd call this with: 你这称之为:

var collection = CreateItemCollection<ItemCollection, Item>();

The problem here is generic constraints, in C# 3.0, have any leeway with regards to variance. 这里的问题是泛型约束,在C#3.0中,有关于方差的任何余地。 The matching is instead fairly strict. 相反,匹配相当严格。 Since ItemCollection derives from CollectionBase<Item> it is not considered to be derived from CollectionBase<ItemBase> even though the types may appear to be compatible. 由于ItemCollection派生自CollectionBase<Item>因此它不被认为是从CollectionBase<ItemBase>派生的,即使这些类型看似兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM