[英]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上搜索的具體術語是Covariance
和Contravariance
。
如果您限制類至少在基類中讀取訪問權限,則可以解決您的情況。 然后,您的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.