c# 协变和逆变
类别:编程学习 浏览量:364
时间:2014-9-26 c# 协变和逆变
c# 协变和逆变
由子类向父类方向转变是协变,用out关键字标识,由父类向子类方向转变是逆变,用in关键字
协变和逆变的应用
一、 数组的协变
Animal[] animalArray =
new
Dog[]{};
说明:声明的数组数据类型是Animal,而实际上赋值时给的是Dog数组;每一个Dog对象都可以安全的转变为Animal。Dog向Animal方法转变是沿着继承链向上转变的所以是协变
二. 委托中的协变和逆变
1、委托中的协变
C# 代码 复制
//委托定义的返回值是Animal类型是父类
public delegate Animal GetAnimal();
//委托方法实现中的返回值是Dog,是子类
static Dog GetDog(){return new Dog();}
//GetDog的返回值是Dog, Dog是Animal的子类;返回一个Dog肯定就相当于返回了一个Animal;所以下面对委托的赋值是有效的
GetAnimal getMethod = GetDog;
2、委托中的逆变
//委托中的定义参数类型是Dog
public delegate void FeedDog(Dog target);
//实际方法中的参数类型是Animal
static void FeedAnimal(Animal target){}
// FeedAnimal是FeedDog委托的有效方法,因为委托接受的参数类型是Dog;而FeedAnimal接受的参数是animal,Dog是可以隐式转变成Animal的,所以委托可以安全的的做类型转换,正确的执行委托方法;
FeedDog feedDogMethod = FeedAnimal;
//定义委托时的参数是子类,实际上委托方法的参数是更宽泛的父类Animal,是父类向子类方向转变,是逆变
三. 泛型委托的协变和逆变
1、 泛型委托中的逆变
//委托声明:
public delegate void Feed<in T>(T target);
//Feed委托接受一个泛型类型T,注意在泛型的尖括号中有一个in关键字,这个关键字的作用是告诉编译器在对委托赋值时类型T可能要做逆变
//先声明一个T为Animal的委托
Feed<Animal> feedAnimalMethod = a=>Console.WriteLine(“Feed animal lambda”);
//将T为Animal的委托赋值给T为Dog的委托变量,这是合法的,因为在定义泛型委托时有in关键字,如果把in关键字去掉,编译器会认为不合法
Feed<Dog> feedDogMethod = feedAnimalMethod;
2、泛型委托中的协变
//委托声明
public delegate T Find<out T>();
//Find委托要返回一个泛型类型T的实例,在泛型的尖括号中有一个out关键字,该关键字表明T类型是可能要做协变的
//声明Find<Dog>委托
Find<Dog> findDog = ()=>new Dog();
//声明Find<Animal>委托,并将findDog赋值给findAnimal是合法的,类型T从Dog向Animal转变是协变
Find<Animal> findAnimal = findDog;
四. 泛型接口中的协变和逆变
1、泛型接口中的逆变
//接口定义:
public interface IFeedable<in T>
{
void Feed(T t);
}
//接口的泛型T之前有一个in关键字,来表明这个泛型接口可能要做逆变
//如下泛型类型FeedImp<T>,实现上面的泛型接口;需要注意的是协变和逆变关键字in
public class FeedImp<T>:IFeedable<T>
{
public void Feed(T t){
Console.WriteLine(“Feed Animal”);
}
}
//使用接口逆变:
IFeedable<Dog> feedDog = new FeedImp<Animal>();
//上面的代码将FeedImp<Animal>类型赋值给了IFeedable<Dog>的变量;Animal向Dog转变了,所以是逆变
2、泛型接口中的协变
//接口的定义:
public interface IFinder<out T>
{
T Find();
}
//泛型接口的泛型T之前用了out关键字来说明此接口是可能要做协变的;如下泛型接口实现类
public class Finder<T>:IFinder<T> where T:new()
{
public T Find(){
return new T();
}
}
//使用协变,IFinder的泛型类型是Animal,但是由于有out关键字,我可以将Finder<Dog>赋值给它
IFinder<Animal> finder = new Finder<Dog>();
标签:接口
您可能感兴趣
- TypeScript定义接口(interface)案例教程(TypeScript定义接口interface案例教程)
- nginx配置访问接口(nginx网站服务如何配置防盗链推荐)
- php中抽象类和接口的区别(PHP抽象类和接口用法实例详解)
- python调用支付宝支付接口(python实现支付宝转账接口)
- laravel增删改查接口(laravel-admin 实现给grid的列添加行数序号的方法)
- laravel接口响应时间(laravel请求参数校验方法)
- jmeter接口性能测试教程(Xmeter API接口测试工具使用方法解析)
- html5的canvas代码(H5最强接口之canvas实现动态图形功能)
- python 微信二维码接口(python实现微信防撤回神器)
- laravel接口请求模拟(Laravel 类和接口注入相关的代码)
- 阿里云网站cdn加速(阿里云CDN刷新链接接口实践)
- python接口自动化接口依赖(python接口自动化十六--参数关联接口后传详解)
- php商城支付接口(php实现银联商务公众号+服务窗支付的示例代码)
- tp5微信支付接口开发案例(PHP实现的微信APP支付功能示例基于TP5框架)
- thinkphp接口开发实例(ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解)
- django框架教程第100讲(详解Django+Vue+Docker搭建接口测试平台实战)
- 冰岛旅游攻略(冰岛旅游攻略及花费八日游)
- 寒假旅游攻略(成都寒假旅游攻略)
- 菲律宾旅游攻略(菲律宾旅游攻略地图)
- 清华大学难考吗(清华大学考研录取分数线)
- 观花盆栽佛肚竹盆景制作及养护(观花盆栽佛肚竹盆景制作及养护)
- 春天养佛肚竹,做好这几件事,叶绿根壮寓意好 越养越旺家(春天养佛肚竹做好这几件事)
热门推荐
- next js上线(Next.js入门使用教程)
- python集合类(Python数据类型之Set集合实例详解)
- html和js代码结合(JS、CSS和HTML实现注册页面)
- pyqt左侧菜单栏(pyside+pyqt实现鼠标右键菜单功能)
- sql server怎么导出数据库(sqlserver复制数据库的方法步骤图文)
- mysql创建用户并给用户授权(MySQL 主从复制中创建复制用户的时机探讨)
- canvas里面图片如何获取(canvas生成带二维码海报的踩坑记录)
- php上传图片视频代码(详解PHP素材图片上传、下载功能)
- css经典技巧(CSS性能优化提高css性能的方法)
- dedecms插件解析(dedecms文章评论功能用法分析)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9