重学c#系列——逆变和协变[二十四]
作者:互联网
正文
什么是逆变和协变呢?
首先逆变和协变都是术语。
协变表示能够使用比原始指定的派生类型的派生程度更大的类型。
逆变表示能够使用比原始指定的派生类型的派生程度更小的类型。
这里student 继承 person。
这里这个报错合情合理。
这里可能有些刚入门的人认为,person 不是 student 的父类啊,为什么不可以呢?
一个列表student 同样也是一个列表的 person啊。
这可能是初学者的一个疑问。
但是实际情况是list<person> 是一个类型, list<student> 是一个类型。
所以他们无法隐式转换是正常的。
但是这样写就可以:
static void Main(string[] args)
{
IEnumerable<Student> students = new List<Student>();
IEnumerable<Person> peoples = students;
}
这样写没有报错,理论上IEnumerable<Student>是一种类型,IEnumerable<Person>是一种类型,不应该能隐私转换啊。
为什么呢?因为支持协变。
协变表示能够使用比原始指定的派生类型的派生程度更大的类型。
他们的结构如上。因为student是person的派生类,IEnumerable<T>原始指定了student,派生程度更大的类型是person,所以IEnumerable<Student>到IEnumerable<Person>符合协变。
协变怎么声明呢:
public interface IEnumerable<out T> : IEnumerable
{
//
// 摘要:
// Returns an enumerator that iterates through the collection.
//
// 返回结果:
// An enumerator that can be used to iterate through the collection.
new IEnumerator<T> GetEnumerator();
}
C# 复制 全屏
这里协变有个特点,那就是协变参数T,只能用于返回类型。
原因是在运行时候还是new List<Student>(),返回自然是Student,那么student 可以赋值给person,这没问题。
那么协变参数T,不能用于参数呢? 是这样的。