簡體   English   中英

如何專門化繼承的列表 <SuperClass> 到清單 <SubClass> 在C#中?

[英]How to specialize an inherited List<SuperClass> to a List<SubClass> in C#?

這聽起來像是一個常見問題,因此,如果您有一個具有List<SuperClass>類型的公共屬性的基類A,並且您在類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;  
    }
}

你不能。 因為按照現狀,如果您通過A接口插入一個SuperClass,則B將失敗,因為無法將SuperClass插入B的SubClass列表中。

您應該在Google上搜索的具體術語是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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM