C#中使用列表成员的类的协方差 [英] Covariance for classes with list members in 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 ComplexElement
s 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屋!