为什么我的派生类不能转换为基类?

时间:2013-04-02 18:16:08

标签: c# base derived

我有以下课程:

public class Item
{
}

public class ItemCollection<TItem> : ICollection<TItem> where TItem : Item, new()
{
}

我有两个派生类:     

public class Feature : Item
{
}

public class Features : ItemCollection<Feature>
{
}

我有一个经理类来管理这样的集合:

public class ItemCollectionManager<TCollection> where TCollection : ItemCollection<Item>, new()
{
}

我尝试使用这个类:

public class FeatureManager : ItemCollectionManager<Features>
{
}

但结果是:

“类型Features必须可转换为ItemCollection<Item>,才能在通用类ItemCollectionManager<TCollection>中将其用作TCollection。”

如前所述,

Features是一个ItemCollection<Feature>

Feature是一个Item

我不认为接口是完成此任务的理想解决方案,但如果提供了原因,我愿意改变。

如果有人能就我的错误提出建议,我们将非常感激。

谢谢。

2 个答案:

答案 0 :(得分:2)

你做不到......

ItemCollection<Feature> features = ...;
ItemCollection<Item> items = features;

这是关于泛型variance(协方差和逆变) - 它只支持接口,代理 - 并且只提供它们的设计方式(用{{1}装饰} / in - 并遵守随之而来的规则)。例如out是(如果您查找其定义,则会看到IEnumerable<>)。有关详细信息,我认为最好阅读更多...

How is Generic Covariance & Contra-variance Implemented in C# 4.0?
Understanding Covariant and Contravariant interfaces in C#
http://msdn.microsoft.com/en-us/library/dd799517.aspx

在您的情况下,您可以设计一个outIItemCollection<out T>) - (理论上)可能支持您需要的投射。但它必须是interface有点简化而且不完全正确,但更容易这样思考 - 规则有点复杂)。

因为你将它命名为'集合',我假设它不仅仅用于枚举,查看项目 - 即如果你有read-only种类(需要Add - 即input parameters)与contra-variance所需的“协方差”冲突。此外,所涉及的任何其他参数可能都不允许您的界面变得协变。

<小时/> 我做的其他一些帖子也相关......

How to make generic class that contains a Set of only its own type or subtypes as Children?

C# generic handlers, what am I misunderstanding?

答案 1 :(得分:1)

在ItemCollectionManager,TItem。

上需要一个额外的泛型参数

我相信你的ItemCollectionManager类定义看起来应该是这样的。

    public class ItemCollectionManager<TCollection, TItem> where TCollection : ItemCollection<TItem>, new(), 
where TItem : Item
    {
    }

现在定义FeatureManager类的方式完全可以接受Item继承TCollection的任何CLASS,因为TCollection的唯一限制是它包含类型Item的类。集合Features仅接受继承Feature类型的Feature个类或类。由于您无法将Item的基本类型添加到Features,因此不应编译。