.NET 4泛型中的Covariance和Contravariance
在介绍.NET 4泛型的covariance和contravariance之前,先介绍下编程语言类型系统的variance的概念。简单的说covariance使得你能够用一个更具体的类来替代一个本该父层的类。在C#中,引用类型的数组是covariant的,这是从当时的Java中学来的特性,例如:
namespace variance2
{
public class Animal { }
public class Dog : Animal { }
class Program
{
static void Main(string[] args)
{
Animal[] animals = new Dog[10];
animals[0] = new Animal();
}
}
}当给animals数组初始化的时候,可以使用它的子类Dog,这里是covariance的。这段代码可以编译通过,但是运行的时候会报如下错误:
Attempted to access an element as a type incompatible with the array.
因为一旦给数组赋值了Dog,实际上它就是一个Dog数组,所以不能再给他赋值Animal。一段能编译通过的代码再运行时发生类型错误并不是好事情,所以在.Net 2引入泛型的时候.net的泛型是invariant的。
List<Animal> listAnimals = new List<Dog>();这样是不能通过编译的。
List<Dog> listDogs = new List<Dog>();
listDogs.Add(new Animal());这样也不能通过编译。.NET2 这样做避免了一些问题,但同时也带来了一些问题,例如: List<Dog> listDogs = new List<Dog>();
IEnumerable<Animal> enumAnimals = listDogs;这样是不能编译通过的。实际上,这种编程场景很常见,而且事实上这是类型安全的,因为通过IEnumerable接口,我们只能从enumAnimals中获取值,而不能给他赋值。
下面举一个contravariance的例子:
public class Animal
{
public int Weight
{
get;set;
}
public string Name
{
get;set;
}
public Animal(string name,int weight)
{
Name=name; Weight=weight;
}
}
public class Dog : Animal
{
public Dog(string name,int weight):base(name,weight)
{
}
}
public class WeightComparer : IComparer<Animal>
{
public int Compare(Animal x, Animal y)
{
return x.Weight - y.Weight;
}
}给动物类加上一个重量的属性,并且实现一个根据重量排序的IComparer类。
class Program
{
static void Main(string[] args)
{
WeightComparer comparer = new WeightComparer();
List<Animal> animals = new List<Animal>();
animals.Add(new Animal("Dog", 4));
animals.Add(new Animal("Mouse", 1));
animals.Add(new Animal("Tiger",44));
animals.Sort(comparer); //works fine
相关新闻>>
- 发表评论
-
- 最新评论 进入详细评论页>>
今日头条
更多>>您可能感兴趣的文章
- 谈.Net委托与线程——创建无阻塞的异步调用(一
- asp.net 六大内置对象(2)
- 微软ASP.NET站点部署指南(11):部署SQL Server数据
- MVC中一个表单实现多个提交按钮(一个action搞定
- winform下通过webclient使用非流方式上传(post)数据和
- 教你如何来恢复一个丢失的数据文件
- ASP.NET数据格式的Format--DataFormatString
- Pro ASP.NET MVC 3 Framework学习笔记之九
- asp.net js模拟Button点击事件
- Asp.net MVC源码分析--Model Validation(Client端)实现(2)