我觉得我的问题非常愚蠢,或者另一种说法是:我在代码中迷失了,现在看到一个解决方法。对问题保持太久,你的视力变得更窄更窄<!> gt; <!> lt;。另外,我对继承,多态性等不够好

这是一个想法:我有多个派生类列表,我想在这些列表上调用泛型函数(访问和修改基类的成员)。我觉得与继承有关,但我无法让它现在正常运作。

以下是我打算做的一个非常简单的例子:

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
}
有帮助吗?

解决方案

要爱变化。 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()约束,或传入(例如)a params T[]

另请注意,IEnumerable<T>在C#4.0 / .NET 4.0中变得协变,所以如果你只传入一个IEnumerable<Baseclass>(而不是一个列表),那么它将起作用<!>“;就像<!>一样; :

private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
   ///...
}

其他提示

如果你只是做foreach,请声明FuncOnBase(IEnumerable<Baseclass> collection),你可以从FuncTest这样打电话:

FuncOnBase(collection1.Cast<Baseclass>());

当您使用List<T>参数声明方法但仅使用其IEnumerable<T>功能时,您将添加在您的代码中没有任何内容的API约束。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top