Covariance for classes with list members in C#

折月煮酒 提交于 2019-12-12 03:24:28

问题


Consider a class hierarchy that looks as below. In essence, there is an abstract ComplexBase with some fields that are common to all classes. Then there is a ComplexClass derived from ComplexBase that, among other things, holds a collection of ComplexElements also derived from ComplexBase.

public abstract class ComplexBase {
  internal abstract string Identifier { get; }
}

public abstract class ComplexClass<T> : ComplexBase where T : ComplexElement {
  internal SortedList<string, T> Elements { get; set; }
}

public abstract class ComplexElement : ComplexBase { }

Implementations of the abstract classes are ComplexClassA and ComplexClassB. The ComplexElement collection of the former only contains instances of ComplexElementA and of the latter only ComplexElementB.

public class ComplexClassA : ComplexClass<ComplexElementA> {
  public ComplexClassA() {
    Elements = new SortedList<string, ComplexElementA>();
  }
}

public class ComplexElementA : ComplexElement { }

public class ComplexClassB : ComplexClass<ComplexElementB> {
  public ComplexClassB() {
    Elements = new SortedList<string, ComplexElementB>();
  }
}

public class ComplexElementB : ComplexElement { }

What I am struggling to understand is how to define a new class TheBigCollection holding various fields and methods, plus a collection of instances of both ComplexClassA and ComplexClassB. A non-working version might look like

public class TheBigCollection {
  internal SortedList<string, ComplexClass> Classes { get; set; }

  public TheBigCollection() {
    Classes = new SortedList<string, ComplexClass>();
  }

  public void Add(string name, ComplexClass element) {
    Classes.Add(name, element);
  }
}

Of course this doesn't compile since ComplexClass is defined with a generic type.

My previous attempt was to use a concept of hiding the lists, but it turns out that this prevents me from accessing the lists of ComplexElements in instances of ComplexClassA or ComplexClassB that I retrieve from the list in TheBigCollection.

I learnt from my previous post that covariance could solve the problem, but I fail to understand how using IEnumerable—which is immutable—can be used to add new elements tho TheBigCollection's list of classes.


回答1:


I tried the following and it works fine.

internal interface IComplexClass
{
    IDictionary<string, ComplexElement> Elements { get; }
}

public abstract class ComplexClass<T> : ComplexBase, IComplexClass where T : ComplexElement
{
    internal SortedList<string, T> Elements { get; set; }

    IDictionary<string, ComplexElement> IComplexClass.Elements
    {
        get { return (IDictionary<string, ComplexElement>)Elements; }
    }
}

Now you could use IComplexClass in TheBigCollection.



来源:https://stackoverflow.com/questions/38629989/covariance-for-classes-with-list-members-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!