我觉得我的问题非常愚蠢,或者另一种说法是:我在代码中迷失了,现在看到一个解决方法。对问题保持太久,你的视力变得更窄更窄><。另外,我对继承,多态性等不够好
这是一个想法:我有多个派生类列表,我想在这些列表上调用泛型函数(访问和修改基类的成员)。我觉得与继承有关,但我无法让它现在正常运作。
以下是我打算做的一个非常简单的例子:
class Baseclass
{
public int ID;
public string Name;
}
class DerivedClass1 : Baseclass
{
}
private void FuncOnBase(List<Baseclass> _collection)
{
// ...
foreach (Baseclass obj in _collection)
{
++obj.ID;
}
// ...
}
private void FuncTest()
{
List<DerivedClass1> collection1 = new List<DerivedClass1>();
collection1.Add(new DerivedClass1() { ID = 1 });
collection1.Add(new DerivedClass1() { ID = 2 });
collection1.Add(new DerivedClass1() { ID = 3 });
FuncOnBase(collection1); // ==> forbidden, cannot convert the derived class list to the base class list
}
答案 0 :(得分:11)
要爱变化。 List<DerivedClass1>
不 a List<Baseclass>
- 否则,FuncOnBase
可能会尝试将Baseclass
添加到列表中,编译器不会发现它
一个技巧是使用通用方法:
private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
// ...
foreach (T obj in _collection)
{
obj.ID++;
}
// ...
}
就我上面提到的示例而言 - 请注意,我们可以在列表中添加T
;特别有用的是,如果我们添加T : new()
约束,或传入(例如)params T[]
。
另请注意,IEnumerable<T>
在C#4.0 / .NET 4.0中变得协变,所以如果只传入IEnumerable<Baseclass>
(而不是列表),它将“按原样”工作:
private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
///...
}
答案 1 :(得分:2)
如果您只是foreach
,请声明FuncOnBase(IEnumerable<Baseclass> collection)
,您可以从FuncTest
拨打这样的电话:
FuncOnBase(collection1.Cast<Baseclass>());
当您使用List<T>
参数声明方法但仅使用其IEnumerable<T>
功能时,您将添加在您的代码中没有任何内容的API约束。