C#中使用列表成员的类的协方差 [英] Covariance for classes with list members in C#

查看:137
本文介绍了C#中使用列表成员的类的协方差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的类层次结构。实质上,有一个抽象的 ComplexBase ,其中一些字段对于所有类都是通用的。然后从 ComplexBase 派生出一个 ComplexClass ,其中包含 ComplexElement s也衍生于 ComplexBase

 公共抽象类ComplexBase {
内部抽象字符串标识符{get; }
}

公共抽象类ComplexClass< T> :ComplexBase其中T:ComplexElement {
内部SortedList<字符串,T>元素{get;组; }
}

public abstract class ComplexElement:ComplexBase {}

抽象类的实现是 ComplexClassA ComplexClassB 。前者的 ComplexElement 集合仅包含 ComplexElementA 的实例,后者仅包含 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 {}

我很难理解的是如何定义一个持有各种字段和方法的新类 TheBigCollection ,以及 ComplexClassA ComplexClassB 。非工作版本可能看起来像

  public class TheBigCollection {
internal SortedList< string,ComplexClass>类{get;组; }
$ b $ public TheBigCollection(){
Classes = new SortedList< string,ComplexClass>();

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


当然,自< $ c> ComplexClass 用泛型定义。

My 先前的尝试是使用隐藏列表的概念,但事实证明这阻止了我访问 ComplexElements ,在 ComplexClassA ComplexClassB 的实例中,我从 TheBigCollection



我从之前的文章中了解到协变可以解决这个问题,但我不明白如何使用 IEnumerable - 它是不可变的 - 可用于添加新元素tho TheBigCollection 的类列表。

解决方案

我尝试了以下方法,它工作正常。 $ c>内部接口IComplexClass
{
IDiction ary< string,ComplexElement>元素{get; }
}

公共抽象类ComplexClass< T> :ComplexBase,IComplexClass其中T:ComplexElement
{
内部SortedList< string,T>元素{get;组; }

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




$ b $现在你可以在TheBigCollection中使用IComplexClass了。 p>

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.

解决方案

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.

这篇关于C#中使用列表成员的类的协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆