变体(variance)是协变(covariance)和抗变(contravariance)的统称,这两个概念在.NET4中引入。实际上,它们己经存在了较长时间了(在.NET 2.0中就可以使用),但在.NET 4之前很难实现它们,因为它们需要定制的编译过程。
要掌握这些术语的含义,最简单的方式是把它们与多态性进行比较。多态性允许把派生类型的对象放在基类型的变量中,例如:
Cow myCow = new Cow("BenM>
Animal myAnimal = myCow;
其中把Cow类型的对象放在Animal类型的变量中,这是可行的,因为Cow派生自Animal。
但这不适用于接口,也就是说,下面的代码不能工作:
IMethaneProducer<Cow> cowMethaneProducer = myCow;
IMethaneProducer<Animal> animalMethaneProducer = cowMethaneProducer;
假定Cow支持IMethaneProducer<Cow>接口,第一行代码就没有问题。但是,第二行代码预先假定两个接口类型有某种关系,但实际上这种关系不存在,所以无法把一种类型转换为另一种类型。可以在泛型接口和泛型委托上定义变体类型参数,以适合上述代码演示的情形。
为使上述代码工作,IMethaneProducer<T>接口的类型参数T必须是协变的。有了协变的类型参数,就可以在IMethaneProducer<Cow>和IMethaneProducer<Animal>之间建立继承关系,这样一种类型的变量就可以包含另一种类型的值,这与多态性类似(但稍复杂些)。
为了完成对变体的介绍,需要看看变体的另一面:抗变。抗变和协变是类似的,但方向相反。抗变不能像协变那样,把泛型接口值放在使用基类型的变量中,但可以把该接口放在使用派生类型的变量中,例如:
IGrassMuncher<Cow> cowGrassMuncher = myCow;
IGrassMuncher<SuperCow> superCowGrassMuncher = cowGrassMuncher;
初看起来似乎有点古怪,因为不能通过多态性完成相同的功能。但是这在一些情况下是一项有效的技术。
已有 22658 名学员学习以下课程通过考试
最需教育客户端 软件问题一手掌握
去 App Store 免费下载 iOS 客户端
点击加载更多评论>>