3

我觉得我的问题很愚蠢,或者换一种说法是:我太迷失在我的代码中,暂时看不到解决方法。在一个问题上停留太久,你的视野会越来越窄><。另外,我对继承、多态性等还不够好

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

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

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
}
4

2 回答 2

11

必须爱变异。AList<DerivedClass1>不是a - 否则,可能会尝试将 a 添加列表中,而编译器不会发现它。List<Baseclass>FuncOnBaseBaseclass

一个技巧是使用通用方法:

private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
    // ...

    foreach (T obj in _collection)
    {
        obj.ID++;
    }

    // ...
}

就我上面介绍的示例而言 - 请注意,我们可以将 a 添加T到列表中;T : new()如果我们添加约束或传入(例如) a ,则特别有用params T[]

另请注意,这IEnumerable<T>在 C# 4.0 / .NET 4.0 中变得协变,因此如果您只传入一个IEnumerable<Baseclass>(而不是列表),它将“按原样”工作:

private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
   ///...
}
于 2009-10-28T07:37:56.500 回答
2

如果你只做一个foreach, declare FuncOnBase(IEnumerable<Baseclass> collection),你可以FuncTest这样调用:

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

当您声明带有List<T>参数的方法但仅使用其IEnumerable<T>功能时,您添加的 API 约束在您的代码中毫无意义。

于 2009-10-28T07:38:08.967 回答