【问题标题】:C# - how to create an inherited generic collection from a factory methodC# - 如何从工厂方法创建继承的泛型集合
【发布时间】:2009-09-08 15:13:38
【问题描述】:

我正在尝试编写一个工厂方法,该方法将创建抽象泛型集合类的派生实例。以下是基类...

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&lt;ItemBase&gt;

有人可以指出我正确的方向吗?谢谢。

【问题讨论】:

    标签: c# constraints factory generic-collections


    【解决方案1】:

    ItemCollection 不是派生自CollectionBase&lt;ItemBase&gt;,因为通用不变性。毕竟,您可以将 ItemBase 添加到 CollectionBase&lt;ItemBase&gt; - 但您不希望将其用于您的 ItemCollection

    您需要在两个类型参数中使方法泛型:

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

    只有集合类型需要无参数构造函数。你可以这样称呼它:

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

    【讨论】:

    • 谢谢。这解决了我的问题,即使我仍然不能完全理解为什么编译器坚持如此严格(如下面的 JaredPar 评论)。
    • @Tim:正如我所说,因为ItemCollection不得允许所有与CollectionBase&lt;ItemBase&gt; 相同的调用。阅读 Eric Lippert 的关于方差的博客系列以了解更多详细信息 - 不幸的是,我现在需要运行,所以没有时间去寻找链接。
    【解决方案2】:

    这里的问题是通用约束,在 C# 3.0 中,在方差方面有任何余地。相反,匹配相当严格。由于 ItemCollection 派生自 CollectionBase&lt;Item&gt;,因此它不被视为派生自 CollectionBase&lt;ItemBase&gt;,即使类型可能看起来兼容。

    【讨论】:

      猜你喜欢
      • 2011-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多