繁体   English   中英

如何转换通用列表 <T> 到基于接口的列表 <T>

[英]How to convert a generic List<T> to an Interface based List<T>

我确信我遗漏了一些简单的东西,但是我试图将所有实现接口的强类型对象列表转换为该接口类型的列表。

下面是一个演示错误的示例:

public void ExampleCode(){
    List<Cube> cubes = new List<Cube>();
    List<Shape> allShapes;
    allShapes = cubes;//Syntax Error
    allShapes = (List<Shape>)cubes;//Syntax Error  
}

public class Cube : Shape
{
    public int ID { get; set; }
    public int Sides { get; set; }
}

public interface Shape
{
  int ID { get; set; }
  int Sides { get; set; }
}

尝试:而不是像那样投射

allShapes = cubes.Cast<Shape>().ToList();

你需要.NET 3.5。 我相信Cast扩展方法可以在System.Linq中找到。

你不能。 因为List<T>ILIst<T>只支持不变类型参数。 这归结为T既用于输入和输出参数(例如返回值)。 否则你可以打破类型安全。

其他接口(例如IEntumerable<T> )确实允许一些差异。

有关反对和共同变化的讨论,请参阅Eric Lippert的博客“ 编码中的神奇冒险 ”。 特别是“ 协方差和逆变 ”标签。

编辑,刚刚添加到“C#常见问题”博客: Covariance和Contravariance FAQ

您所指的是通用协方差,并且不受c#3支持。但是,它受到c#4(.NET 4 / VS 2010)的支持,您可以在此处阅读更多相关内容:

通用接口的方差

话虽如此, IList<T>不是协变的(因为它接受并暴露了T )。 另一方面, IEnumerable<T>是协变的(因为它不接受T )。

你不能这样做,因为通过这种方式铸造你可能会失去所有类型的安全性。 对于instnce,将List<Shape>List<object>将导致任何类型的对象都可以添加到列表中,这将完全不一致。

你也可以这样做:

allShapes = cubes.ConvertAll(x => (Shape)x);

或者如果你在.NET 2.0中这样做:

allShapes = cubes.ConvertAll<Shape>(delegate(Cube c){
    return (Shape)c;
});

您不能在类型列表之间进行转换,即使类型本身是可转换的。 您需要创建一个新列表并通过迭代原始列表或使用ConvertAll来填充它。 有关示例代码,请参见http://www.dev102.com/2008/05/15/how-to-convert-listt1-to-listt2/

如果将allShapes定义为IEnumerable,则此方法有效

在C#4.0中,您可以简单地指定allshapes = cubes

对于C#3.5,您可以使用allShapes = cubes.Select(c =>((Shape)c));

但无论如何你需要使用IEnumerable而不是List

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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