C# 继承和泛型约束

C# 继承和泛型约束,c#,generics,inheritance,collections,C#,Generics,Inheritance,Collections,我一直在为集合、泛型和继承而挣扎。很抱歉,我不知道如何用正确的方式表达我的问题,但我相信这段代码已经足够了 public class A { public IList<C> sequenceOfC; public A(IList<C> sequenceOfC) { this.sequenceOfC = sequenceOfC; } } public class B : A { public B(IList<

我一直在为集合、泛型和继承而挣扎。很抱歉,我不知道如何用正确的方式表达我的问题,但我相信这段代码已经足够了

public class A
{
    public IList<C> sequenceOfC;

    public A(IList<C> sequenceOfC)
    {
        this.sequenceOfC = sequenceOfC;
    }
}

public class B : A {
    public B(IList<D> sequanceOfC) : base(sequanceOfC) { } //compile time error 
    // Error 2  Argument 1: cannot convert from 
    // 'System.Collections.Generic.IList<ConsoleApplication.D>' 
    // to 'System.Collections.Generic.IList<ConsoleApplication.C>'  
}

public class C { }

public class D : C { }
公共A类
{
公共图书馆;
公共A(IList sequenceOfC)
{
this.sequenceOfC=sequenceOfC;
}
}
B级:A级{
公共B(IList sequanceOfC):基(sequanceOfC){}//编译时错误
//错误2参数1:无法从转换
//'System.Collections.Generic.IList'
//至“System.Collections.Generic.IList”
}
公共类C{}
公共类D:C{}

我不明白为什么我会看到这个错误。cd是从C继承来的,一切都应该继续下去,不是吗?

问题是
IList
不是协变的。因此,编译器无法确保在任何情况下都能将
D
转换为
C
。解决方案是使用
IEnumerable
初始化列表:

public class A
{
    public IList<C> sequanceOfC;

    public A(IEnumerable<C> sequanceOfC)
    {
        this.sequanceOfC = new List<C>(sequanceOfC);
    }
}

public class B : A 
{
    public B(IList<D> sequanceOfD) : base(sequanceOfD) { }  
}
公共A类
{
公共IList sequanceOfC;
公共A(IEnumerable sequanceOfC)
{
this.sequalceofc=新列表(sequalceofc);
}
}
B级:A级
{
公共B(IList sequenceofd):基(sequenceofd){}
}

如果D继承自C,并且IList是协变的,则可以编写:

public class E : C
{}

IList<D> source = new List<D>();
IList<C> target = source;
target.Add(new E());
公共类E:C
{}
IList source=新列表();
IList目标=源;
target.Add(新的E());

这显然是错误的,因为将E添加到D的列表中

错误是由于
IList
T
中是不变的。为了使任务有效,它必须是协变的。您必须使用
IEnumerable
或者相反。@PatrykĆwiek:因为
C
是一个类,所以
IList
的声明是完全有效的。@Aschratt很好,我被命名搞糊涂了。感谢您的更正,我将其从原始注释中删除,据我所知,删除标记在注释(?)中不起作用。编译器不会像您或我那样看待列表。您在考虑“C的列表”和“D的列表”,事先了解C和D之间的关系,而编译器只看到封闭类型。自类型化(IList)!=typeof(IList)它不能完成任务。@mungflesh我很清楚。但在我所处的情况下,如何解决这个问题呢?但我认为,从现有的序列中创建新的序列并不是一种很好的做法。我指的是性能和优化。不是吗?因为您使用的是一个类列表,所以不会对性能造成太大影响。类实例是引用类型,因此仅复制引用。这实际上相当快。Linq的
ToList
也做了同样的事情。好吧,但是如果我们发现IEnumerable包含1000000项的术语,那么我创建了一个新的列表。我是对的,在创建列表时,它将为1000 000个项目保留额外的内存?不,只是为1.000.000个引用,而不是整个对象。@frankie:作为替代,您必须更改您的设计。对
sequalceofc
-成员使用
IEnumerable
,只需复制构造函数传递的引用即可。其余部分取决于您的设计。例如,这会阻止您轻松添加元素。您如何处理这种情况几乎不取决于您的设计。