2013-04-02 81 views
1

我有以下类别: 为什么我的派生类不能传递给基类?

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必须是为了在泛型类ItemCollectionManager<TCollection>使用它作为TCollection转换为ItemCollection<Item>”。

而且如前面提到的,

Features是-一个ItemCollection<Feature>

Feature是-一个Item

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

如果有人可以建议我在做什么错误,将非常感激。

谢谢。

回答

2

你不能做......

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

这是关于仿制药variance(协方差和逆变即是) - 而且它仅支持接口,委托 - 而且只提供他们这样设计的 (用in/out装饰 - 并遵守随之而来的规则)。例如IEnumerable<>是(如果你查找它的定义,你会看到out)。欲了解更多细节,我认为最好阅读更多...

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

在你的情况,你可以设计一个IItemCollection<out T>interface) - 即(理论上)可能支持你所需要的铸造。但它必须是read-only有点简化,并不完全正确,但更容易这样想 - 规则有点复杂)。

既然你命名它“收集”我假设它不只是枚举,查看项目 - 也就是说,如果你有一个排序(要求input parameters - 即contra-variance)的Add与冲突的“协方差“,您需要upcasting。还有其他任何参数可能不允许你的接口进行协变。


我也做了一些相关的其他职位...

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?

+0

+1为协方差和链接。我不知道你可以用in/out来装饰类型参数。 –

+0

@ MalcolmO'Hare不客气 - 是的,它可能在某些情况下很有用 – NSGaga

1

您需要在ItemCollectionManager,TItem上添加一个通用参数。

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

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

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

+1

实现它的方式产生进一步问题的路线,我不相信供应TItem是必要的因为无论如何它只是一个'Item'。但是,如果这是必需的,请你能解释一下为什么? –

+0

我已经添加了一些解释。如果它仍然不清楚,那么让我知道,我会尽力解释它。 –

相关问题