Delegate(委托)中的Covariance(协变)和Contravariance(逆变)
来源:互联网 发布:淘宝网身份认证复核 编辑:程序博客网 时间:2024/05/17 11:04
在Delegate当中,Variance(变异)是比较简单的理念,但不能深入理解的话,还是感觉比较疑惑的。
Covariance(协变)
- Return types are compatible
- A delegate variable can be used with a method that retures a type that is derived from the delegate's returned type
一个委托变量可以被赋值于一个方法,即使这个方法的返回值是继承于委托所定义时的返回值。
代码示例:
public class Person { } public class Employee : Person { } class Program{ static void Main(string[] args) { Func<Person> personMaker; personMaker = MakePerson; personMaker = MakeEmployee; Func<Employee> employeeMaker; //employeeMaker = MakePerson(); //这个是不能通过编译的 //employeeMaker = MakePerson2(); //这个是不能通过编译的 employeeMaker = MakeEmployee; } private static Person MakePerson() { return new Person(); } private static Person MakePerson2() { return new Employee(); } private static Employee MakeEmployee() { return new Employee(); }}
- Func<Person>很显然可以被赋值于一个返回Person的方法。但如果一个方法返回Employee呢?因为Employee是继承自Person,Employee就是一个Person,所以即使是返回Employee的方法也是可以赋给Func<Person>的。这里就是Covariance所支持的理念。
- Func<Employee>很显然可以被赋值于一个返回Employee的方法。但如果一个方法返回Person呢?因为Person不是Employee,即使Person实际上指的是Employee,这样的赋值也是不能通过编译的。
Contravariance(逆变)
- Parameter types are compatible
- A delegate variable can be used with a method that takes parameters that are ancestors of the delegate's parameter types
一个委托变量可以被赋值于一个方法,即使这个方法的参数是委托所定义时的参数的父类。
代码示例:
public class Person { } public class Employee : Person { } class Program{ static void Main(string[] args) { Action<Person> personProcessor; personProcessor = ProcessPerson; //personProcessor = ProcessEmployee; //这个是不能通过编译的 personProcessor(new Person()); personProcessor(new Employee()); Action<Employee> employeeProcessor; employeeProcessor = ProcessPerson; employeeProcessor = ProcessEmployee; //employeeProcessor(new Person()); //这个是不能通过编译的 employeeProcessor(new Employee()); } private static void ProcessPerson(Person person) { } private static void ProcessEmployee(Employee employee) { }}
在以上示例中,
- Action<Person>在最终调用的时候必须是Person或它的子类。因为Employee也是Person,所以personProcessor可以传入Person或者Employee。
- Action<Employee>在最终调用的时候必须是Employee或它的子类。传入Person的时候,那就不能通过编译。即使Person实际上代表的是Employee,也不能通过编译。
- 为什么方法ProcessEmployee不能赋于personProcessor?理由很简单:ProcessEmployee处理的是Employee,但personProcessor只能处理Person。把一个Person传给ProcessEmployee,这是不行的。
- 为什么ProcessPerson能赋值给employeeProcessor?因为ProcessPerson是处理Person的,但Employee也是Person,所以从概念上讲,但我们把ProcessPerson赋给employeeProcessor的时候,也就是准备处理Person,当employeeProcessor最终调用的时候传入的是Employee,所以应该完全可以。这里就是Contravariance所实现的理念。
- 简言之,Action<Person>最终是处理Person的,ProcessPerson可以处理Person,但ProcessEmployee不可以处理Person。Action<Employee>最终是处理Employee的,ProcessPerson和ProcessEmployee是可以处理Employee的。
但我相信经过以上的实例和讲解,大家应该能深刻地理解了委托中的协变和逆变!
阅读全文
0 0
- Delegate(委托)中的Covariance(协变)和Contravariance(逆变)
- .Net 2.0 新功能:委托中的协变与逆变(Covariance and Contravariance in Delegates)
- 协变(covariance),逆变(contravariance)与不变(invariance)
- 协变(Covariance)与逆变(Contravariance)
- Covariance and Contravariance in Generics(泛型中的协变和逆变)
- 对协变和逆变的理解(Contravariance and Covariance)
- C# 入门(13) 泛型(generic)、协变(convariance)、逆变(contravariance)
- 委托中的协变和逆变
- 委托中的协变和逆变(C# 编程指南)
- 委托中的协变和逆变(C# 编程指南)
- C#中的协变与抗变(逆变)
- C#委托中的协变和逆变
- 委托中的协变与逆变
- c# 委托 协变和逆变
- 7.1.8 委托中的协变和抗变
- C#委托中的协变与逆变
- 理解 C# 泛型接口中的协变与逆变(抗变)
- C#高级程序设计(五)——代理中的协变和逆变
- 十六进制转换的高效算法
- 培训:基于Kubernetes的DevOps实践
- gson改变输出字段的顺序
- Unity Attribute学习总结
- 输出100以内所有含7或7的倍数的值
- Delegate(委托)中的Covariance(协变)和Contravariance(逆变)
- #ifndef 和 #program once 的区别
- Objective-C Runtime 运行时之四:Method Swizzling
- 在Linux server版上安装node.js
- C++学习笔记--new和namespace
- REDIS源码解析
- Linux批量操作------mov转MP4
- Robot Framework
- 鼠标放上去图片变大 css