上传和通用列表

时间:2009-04-08 14:54:59

标签: c# .net

我有以下类层次结构:

public abstract class BaseData
{
  //some properties
}

public class CoData : BaseData
{
  //some properties
}

我正在使用一个需要返回类型为List<BaseData>的方法。在该方法中,我可以访问List<CoData>

public List<BaseData> Save()
{
  List<CoData> listCoData = GetData();
  return listCoData;
}

如果我理解正确,我可以从CoData转发到BaseData。但是,当我有一个列表时,即使我明确地试图进行类型转换,它也会出错。

错误:

Error   118 Cannot implicitly convert type 'System.Collections.Generic.List<CoData>' to System.Collections.Generic.List<BaseData>'

修改

mquander的转换方法似乎在3.0中适用于我

是否也以同样的方式完成了向下转换?来自

即,我可以这样做 - List<CoData> listCoData = listBaseData.Cast<BaseData>().ToList();

4 个答案:

答案 0 :(得分:10)

是;欢迎来到差异。最终,不是 BaseData的列表 - 例如,如果你有另一个子类,List<BaseData>会(在编译时)让你.Add它...但运行时类型不会让你。编译器阻止你犯错。

在某些情况下,泛型可以在这里提供帮助......我在this blog entry结尾讨论这个问题。请注意,.NET 4.0差异不适用于列表。

答案 1 :(得分:7)

这对于您的集合的参数称为“协方差”,而C#现在不支持这种协方差。在C#4.0中,用户定义的类型和一些内置类型(如IEnumerable<T>)将支持此功能。

与此同时,你可以通过创建一个带有显式演员的新枚举来解决这个问题(你可能想考虑将你的东西的返回类型更改为IEnumerable<T>,这样你就不必实际不断烹饪新的收藏品:)

public List<BaseData> Save()
{
    List<CoData> listCoData = GetData();
    return listCoData.Cast<BaseData>().ToList();
}

根据GetData的工作原理,您可能还会考虑这样的结构:

public List<T> Save<T>() where T : BaseData
{
    return listCoData = GetData<T>();
}

编辑:实际上,正如Marc和其他人无疑会指出的那样,List<T>不能像这样协变,因为你可以添加成员,如果它是破坏类型安全的话。但是,如果您发回了IEnumerable<T>,则可以在此处使用协方差。

编辑2 :回答您的其他问题:

  

我可以这样做吗?    List<CoData> listCoData = listBaseData.Cast<BaseData>().ToList();

没有。 listBaseData.Cast<BaseData>().ToList();返回List<BaseData>类型的对象,该对象无法直接转换为List<CoData>。这就是为什么我们必须首先去做这个努力。

答案 2 :(得分:2)

mquander解决方案的另一个变体是实现Save as:

public List<BaseData> Save()
{
    List<CoData> listCoData = GetData();
    return listCoData.ConvertAll<BaseData>(
        delegate(CoData c) { return c as BaseData; });
}

这将允许您在匿名委托中进行一些额外的处理,而不仅仅是强制转换。

要记住的重要一点是,当CoData继承自BaseData时,List不会从List继承。

答案 3 :(得分:1)

您必须等到C#4.0才能使用generic covariance