在泛型集合多态类型参数 [英] Polymorphic Type Parameters in Generic Collections

查看:114
本文介绍了在泛型集合多态类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么C#编译器不允许多态型(T)的泛型集合参数(即列表[T])?

Why does the C# compiler not allow polymorphic type (T) parameters in generic collections (ie, List[T]) ?

以一流的'A'和' b'例如,在'b'是的子类A

Take class 'A' and 'B' for example, where 'B' is a subclass of 'A'

class A { }
class B : A { }

和考虑一个函数,类型的列表'A'

and consider a function that takes a list of type 'A'

$

void f(List<A> aL) { }

that gets called with a list of type 'B'
List<B> bL = new List<B>();

f(bL);



给出以下错误

The following error is given

ERROR: cannot convert from List<B> to List<A>



什么语义规则被侵犯?

What semantic rule is being violated ?

也有一个优雅的意思,为此,除了通过循环和铸造每个元素(我要加点糖请)?谢谢

Also is there an "elegant" mean to this end, aside from looping through and casting each element (I want some sugar please) ? Thanks.

推荐答案

列表< B> 根本就不是一个亚型列表与LT; A> 。 (我从来没有肯定什么协变,什么逆变就是在这种背景下,所以我会坚持以子类型)。在那里你做到这一点考虑这样的情况:

List<B> simply is not a subtype of List<A>. (I'm never sure about what "covariant" and what "contravariant" is in this context so I'll stick with "subtype".) Consider the case where you do this:

void Fun(List<A> aa) {
    aa(new A());
}

var bb = new List<B>();
Fun(bb); // whoopsie

如果你想要做的是什么允许将有可能增加一个 A b ■哪些显然不是类型安全的列表。

If what you want to do was allowed it would be possible to add an A to a list of Bs which is clearly not type-safe.

现在,显然有可能的阅读的从列表安全,这也是为什么C#让你创建的协(即只读)接口 - 这让编译器知道这是不可能通过他们造成这种损坏。如果你只需要读访问,对集合,通常一个是的IEnumerable< T> ,所以你的情况,你可能只是使该方法:

Now, clearly it's possible to read elements from the list safely, which is why C# lets you create covariant (i.e. "read-only") interfaces - which let the compiler know it's not possible to cause this sort of corruption through them. If you only need read access, for collections, the usual one is IEnumerable<T>, so in your case you might just make the method:


$ b

void Fun(IEnumerable<A> aa) { ... }

and use the Enumerable methods - most should be optimised if the underlying type is List.

不幸的是,由于C#泛型的东西是如何工作的,的的不能变可言,只有接口。而据我所知,所有的集合接口比富裕的IEnumerable< T> 是读写。你可以在技术上使自己的协变封装接口,仅公开您需要的读操作。

Unfortunately, because of how the C# generics stuff works, classes can't be variant at all, only interfaces. And as far as I know, all the collection interfaces "richer" than IEnumerable<T> are "read-write". You could technically make your own covariant wrapper interface that only exposes the read operations you want.

这篇关于在泛型集合多态类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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