具有通用对象的集合

时间:2011-02-14 13:48:00

标签: c# oop collections

有一种方法可以将基础对象列表作为参数。

abstract class Base {}
class MyClass:Base {}
//...
void Method(List<Base> list) {}

当我调用该方法时,我想传递派生对象的列表。

var derivedList = new List<MyClass>();
Method(derivedList);

但我不能这样做,因为派生的集合与基础对象的集合不同。 处理这种情况的最佳做法是什么?现在我正在使用我的扩展.ToBase(),我创建了新的集合,但我认为有更好的解决方案。

感谢。

5 个答案:

答案 0 :(得分:11)

让您的Method通用:

public void Method<T>(List<T> list) where T : Base
{
    //Do your stuff
}

答案 1 :(得分:6)

如果方法仅读取值,则可以声明为:

void Method(IEnumerable<Base> list)

这样,您的调用代码在C#4 / .NET 4中可以正常工作而无需任何更改。在.NET 3.5中,您可以使用

Method(derivedList.Cast<Base>());

如果您的方法值添加到列表中,则通用协方差不会,不应该工作。毕竟,您不希望将对Base派生的某些其他类的实例的引用添加到您的List<MyClass>,是吗?

使Method泛型(如Klaus所建议的)也适用于各种情况,但也会使代码更复杂。在不知道你的方法做什么的情况下很难说这是否是一种好的方法......虽然它绝对值得尝试。

答案 2 :(得分:4)

在C#4.0中实现了协调/反差异,这使您可以在需要List<MyClass>的方法中直接传递List<Base>而无需更多工作。

在C#3.5中,您可以使用Cast<T>()扩展方法将一个类型的可枚举转换为另一个类型,这样您就可以将其转换为基类型(每个条目的转换成本) )。您似乎已经使用扩展方法.ToBase()

完成了这项工作

答案 3 :(得分:0)

这是因为List<MyClass>不是List<Base>

你能做的是:

Method(derivedList.Cast<Base>().ToList());

答案 4 :(得分:0)

鉴于现有的Method签名,没有更好的解决方案。你想要做什么可以用原始数组完成,每个人都后悔。问题是,如果你传递某人List<Base>,那么允许他们放在Base或从中获取的任何内容。但他们不能,因为它真的是List<MyClass>。如果允许的话,它会打破很多的东西。制作新系列是最佳选择。