参数'Group <iitem>'

时间:2016-05-23 21:32:46

标签: c# generics

我正在尝试组建这样的架构:

      • 物品
        • 属性
        • 属性
      • 物品
        • 属性
        • 属性
  • [...]

然后我尝试像这样实例化这个架构:

var sections = new List<ISection>
{
    new Section("Section Header", new List<Group<IItem>>
    {
        new SpecificGroupType1(token, "GroupName")
    }
};

然后,SpecificGroupType1会旋转一个适当的IItem类型的新列表。

但是我收到了以下错误:

Argument SpecificGroupType1 is not assignable to parameter type Group<IItem>

我不太清楚为什么,因为SpecificGroupType1继承自Group。

完整的体系结构看起来像这样(我省略了IAttribute的东西,因为我遇到的问题发生在IAttribute的东西甚至涉及之前):

Section.cs

public interface ISection { // Stuff }

public class Section : ISection
{
    public Section(string sectionName, IList<Group<IItem>> groups)
    {
        Name = sectionName;
        Groups = groups;
    }
}

Group.cs

public interface IGroup { // Stuff }

public abstract class Group<T> : IGroup where T : IItem
{
    protected Group(JToken token, string groupName)
    {
        Name = groupName;
        Items = new List<IItem>();

        foreach (var itemToken in Token.Children())
        {
            Items.Add((Item)Activator.CreateInstance(typeof(T), itemToken);
        }
    }

    public string Name { get; internal set; }
    public JToken Token { get; internal set; }

    protected IList<IItem> Items { get; set; }
}

SpecificGroupType1.cs

public class SpecificGroupType1 : Group<SpecificItemType1>
{
    public SpecificGroupType1(JToken token, string groupName) : base(token, groupName) {}

    // Stuff
}

Item.cs

public interface IItem { // Stuff }

public abstract class Item : IItem
{
    protected ConfigurationItem(JToken token)
    {
        Attributes = new List<IAttribute>();
        Token = token;
    }

    public IList<IAttribute> Attributes { get; set; }
    public JToken Token { get; set; }
}

SpecificItemType1.cs

public class SpecificItemType1 : Item
{
    public SpecificItemType1(JToken token) : base(token) {}

    // Stuff
}

1 个答案:

答案 0 :(得分:2)

从根本上说,这是您的通用参数的问题。考虑这个简化的例子。

// does not compile
Group<IItem> g = new SpecificGroupType1(token, "GroupName");

// does compile
Group<SpecificItemType1> g = new SpecificGroupType1(token, "GroupName");

问题是SpecificGroupType1实现了类Group<SpecificItemType1> Group<IItem>相同。如果您希望能够以这种方式使用更多派生的泛型参数类型,则需要使用协变泛型参数声明。在C#中,这只能在接口而不是类上进行,因此您可能需要重构一下。它会是这样的。

interface IGroup<out T> : IGroup where T: IItem {
    // declarations
}

请注意out关键字。