假设我有以下代码:
public class CBase: AbstractC,IRenderable
{
//code here
}
public class CBaseGroup
{
private List<IRenderable> CCollection;
public CBaseGroup(List<IRenderable> c)
{
CCollection=c;
}
}
public class CGroup:CBaseGroup
{
public CGroup(List<CBase> c):base(c)
//here fails because cannot convert List<CBase> to List<IRenderable>
{
}
}
为什么不编译?
请随意提出一个合适的标题。
来自Matthew Scharley的回答我发现代码应该是这样的:
public class CGroup:CBaseGroup
{
public CGroup(List<CBase> c):base(c.Cast<IRenderable>().ToList())
// cast to list since I'm not using IEnumerable
{
}
}
这至少满足编译器。
答案 0 :(得分:4)
要获得您想要的效果,您需要执行类似
的操作public class CBaseGroup<T> where T : IRenderable
{
private List<T> CCollection;
public CBaseGroup(List<T> c)
{
CCollection=c;
}
}
public class CGroup:CBaseGroup<CBase>
{
public CGroup(List<CBase> c):base(c)
{
}
}
将特定类型的IRenderable
注入基类。
答案 1 :(得分:2)
C#3.5不支持逆变和协方差。我相信我听说C#4.0会(如果我错了,有人会纠正我。)
有关此问题的更广泛讨论,have a look at this other question。
答案 2 :(得分:0)
那么,在第1行,您需要在任何接口
之前包含父类public class CBase: AbstractC, IRenderable
答案 3 :(得分:0)
这是一个协方差问题,因为C#3.5不支持这种泛型类型转换。对C#4.0中的泛型共同和反对方差将有更多的支持。
以下类型的转化工作正如我们所期望的那样,已经多次完成
IRenderable renderable = cbaseObject as IRenderable;
更具体的类型cbaseObject正在类层次结构中转换为更通用的类型IRenderable。但是,以下类似于您的情况
List<CBase> listOfCBaseObjects = new List<CBase>();
IEnumerable<IRenderable> renderables = listOfCBaseObject as IEnumerable<IRenderable>;
将无效,因为当前的C#版本不支持它。
但是,自C#1.0以来,支持包含引用类型的数组的协方差。见Eric Lippert's blog port。因此,如果您执行以下操作,转换将起作用:
CBase [] cbaseObjects = new CBase[] { new CBase(),new CBase()};
IRenderable [] renderables = cbaseObjects as IRenderables[];
或者,如果需要,可以更改CBase和CBaseGroup构造函数以获取数组而不是列表。这样你就可以做到以下几点:
//constructor
public CBaseGroup(IRenderable[] c)
//constructor
public CGroup(CBase[] c):base(c as IRenderable[])
这应该有用。