繁体   English   中英

C#接口实现和通用集合问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM