如何专门化继承的List到List在c#

本文关键字:List SubClass SuperClass 专门化 继承 | 更新日期: 2023-09-27 18:10:01

这听起来像是一个常见的问题,那么如果你有一个基类a,它的公共属性类型为List<SuperClass>,并且你在类B中继承了这个列表,但是想要为列表使用一个更专门的类型参数,那么最佳实践是什么呢:

class SuperClass 
{
    public bool Flag;
}
class SubClass : SuperClass 
{
    public int Number;
}
class A
{
    public List<SuperClass> Elements { get; }
}
class B : A
{
   public List<SubClass> Elements { get; set; }
}

那么如何用一个新列表覆盖Elements列表,但仍然确保它将被访问,如果另一个类只知道a对象?

class C
{
    List<A> AList;
    void FillList()
    {
        AList.Add(new B());
    }
    void DoSomething()
    {
        foreach (var a in AList)
            forach(var super in a.Elements)
                super.Flag = true;  
    }
}

如何专门化继承的List<SuperClass>到List<SubClass>在c#

不能。因为就目前而言,如果通过a接口插入一个超类,B就会失败,因为超类不能插入到B的子类列表中。

你应该谷歌的具体术语是CovarianceContravariance

如果您限制类至少在基类中只能读取访问,则可以解决您的情况。然后在B类中可以有两个只读属性,一个是专门化的,一个不是专门化的,但返回专门化的版本。

我试过了。

class Program {
    static void Main(string[] args) {
        var c = new C();
        c.FillList();
        c.DoSomething();

        Console.ReadKey();
    }
}

class C {
    List<A> AList;
    public void FillList() {
        AList = new List<A>();
        var a = new A();
        a.Elements = new List<SuperClass>() { new SubClass(), new SuperClass() };
        AList.Add(a);
        var b = new B();
        b.Elements = new List<SubClass>() { new SubClass(), new SubClass() };
        AList.Add(b);
    }
    public void DoSomething() {
        foreach (var a in AList)
            foreach (var super in a.Elements) { 
                super.Flag = true;
                Console.WriteLine(super.GetName());
            }
    }
}

class SuperClass {
    public bool Flag;
    public virtual string GetName() { return "super"; } 
}
class SubClass : SuperClass {
    public SubClass() { }
    public SubClass(SuperClass x) { }
    public int Number;
    public override string GetName() { return "sub"; } 
}
class A {
    public virtual IEnumerable<SuperClass> Elements {
        get{
            return elementList.AsEnumerable();
        }
        set {
            elementList = value.ToList();
        }
    }
    private List<SuperClass> elementList;
}
class B : A {
    public override IEnumerable<SuperClass> Elements {
        get {
            return elementList.AsEnumerable();
        }
        set {
            elementList = value.Aggregate(new List<SubClass>(), 
                                (acc, x) => {
                                    if (x is SubClass) 
                                        acc.Add((SubClass)x);
                                    else 
                                        acc.Add(new SubClass(x)); 
                                    return acc; });
        }
    }
    private List<SubClass> elementList;
}

我使用IEnumerable。调用B类的setter属性时,将IEnumerable<SuperClass>转换为List<SubClass>

相关文章: