[英]C# interface implementation and generic collections question
假设我有以下代码:
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
{
}
}
这至少满足编译器的要求。
为了获得想要的效果,您需要执行以下操作
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
注入基类。
C#3.5不支持逆变和协变。 我相信我已经听说过C#4.0将(如果我做错了,请纠正我。)
要对此进行更广泛的讨论,请查看另一个问题 。
好吧,在第一行,您需要在任何接口之前包括父类
public class CBase: AbstractC, IRenderable
这是一个协方差问题,因为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的博客端口 。 因此,如果您执行以下操作,则转换将起作用:
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[])
这应该工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.