有一种方法可以将基础对象列表作为参数。
abstract class Base {}
class MyClass:Base {}
//...
void Method(List<Base> list) {}
当我调用该方法时,我想传递派生对象的列表。
var derivedList = new List<MyClass>();
Method(derivedList);
但我不能这样做,因为派生的集合与基础对象的集合不同。 处理这种情况的最佳做法是什么?现在我正在使用我的扩展.ToBase(),我创建了新的集合,但我认为有更好的解决方案。
感谢。
答案 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>
。如果允许的话,它会打破很多的东西。制作新系列是最佳选择。