小谈C#泛型
(一)泛型的由来
泛型是CLR2.0新增的,泛型兼具可重用性,类型安全和效率。泛型的本质就是在程序第一次编译的为IL代码的时候,就会帮我们生成一个占位符,在git即时编译的时候,就会把占位符替换为真实的类型。
泛型的语法很简单,也没啥好说的。在我们编程中,经常碰到逻辑非常相似的模块,但是参数不一样的情况,这个时候就要考虑用到泛型。
(二)泛型的种类
1、泛型方法
2、泛型类
3、泛型接口
4、泛型委托
这里顺带提一下,泛型类和泛型接口的继承问题,大家可以自己尝试一下。
(三)泛型约束
有约束才有自由,有权利才有义务;
1、基类约束
2、接口约束
3、New()
4、引用类型约束(Class 约束)
5、值类型约束(Struct约束)
这里需要特别注明:泛型方法的返回值的问题,用default(T)
(四)协变,逆变
下面来说说,今天的重点,协变和逆变。
基本概念:out 关键字是用来协变的,in关键字是用来逆变的,协变和逆变只发生在泛型接口和泛型委托上面。
下面直接上代码,首先定义了两个类,一个是鸟类,一个是麻雀类,麻雀类继承自鸟类。
public class Bird
{
public int Id { get; set; }
} public class Sparrow:Bird
{
public string Name { get; set; }
}
下面是简单里氏替换原则,相信大家都能理解;
Bird bird=new Bird();
//这个不会报错,里氏替换原则
Bird sparrow=new Sparrow();
//下面这种做法会报错
//Sparrow sparrow2=new Bird();
再到下面这种情况
List<Bird> birdList1=new List<Bird>();
//这个会报错,这个意思就是一群麻雀,等于一群鸟,在我们自己的逻辑上是没有问题的
//但是程序呢,只认父子关系,两个List之间没有父子关系。
//List<Bird> birdList2=new List<Sparrow>();
//使用下面这个方法转换一下就好了。
List<Bird> birdList2 = new List<Sparrow>().Select(d=>(Bird)d).ToList();
微软为了解决上面这种情况,在我们自己的逻辑上认为,一群麻雀肯定是一群鸟的,所以就引入了协变这个概念。协变呢,在我们平时自己编程中,确实很少用到,但是在微软的框架里面却经常看到,连最常见的IEnumerable接口是支持协变的,看定义如下:

所以刚刚那个例子可以这么写:
IEnumerable<Bird> birds = new List<Sparrow>();
//这个协变呢,声明都是基于基类的,让我们的面向抽象的编程变得更加彻底。
//微软自己给自己打的补丁。
//其实虽然这个是协变,内部还是帮我们像上面一样,进行了类型转换,只不过这个过程是微软自己帮我们做了。
//还要特别说明一点协变,只能是返回结果。
public interface IMyList<out T>{
}
public class MyList<T>:IMyList<T>{
}
第二个是自己写的支持协变的做法。
协变的内容大概就是这么多了,下面来讲讲逆变,逆变和协变刚好相反,是声明派生类,然后用父类来赋值,这个就有点感觉像违法我们的面向对象的感觉。

上面这种就叫做逆变。逆变就是把父类反转赋值给子类。
其实.net framework里面很多关于协变,逆变的,尽管我们可能自己写代码用不到,但是我们也应该要了解和学习。
小谈C#泛型的更多相关文章
- DevStore开发人员服务有奖征文:小谈新浪微博开放平台
DevStore开发人员服务有奖征文:小谈新浪微博开放平台 笔者接入新浪微博开发平台也有一段时间了,对整个平台的接入也算比較熟悉,新浪提供了统一的API接口,能够让开发人员更方便的使用API来实现自己 ...
- 小谈Java里的线程
今天,我们来谈一谈Java里的线程. 一.进程与线程的基本概念 大家可能没听过线程这个概念,但是相信,用计算机的朋友都听过进程这个概念.打开电脑的任务管理器,我们就可以看到许多进程.它们主要分为三类, ...
- 浅谈Java泛型中的extends和super关键字(转)
通配符 在本文的前面的部分里已经说过了泛型类型的子类型的不相关性.但有些时候,我们希望能够像使用普通类型那样使用泛型类型: 向上造型一个泛型对象的引用 向下造型一个泛型对象的引用 向上造型一个泛型对象 ...
- 浅谈C#泛型
一.为什么要提出泛型的概念 我们在声明对象或者方法中,对象中成员变量的定义或者函数参数都传递都要指定具体的对象类型,但是有的时候参数的类型是变化的,但是实现的功能却又差不多,这个时候我们就想,是否存在 ...
- 小谈Scrum敏捷开发流程
一晃眼,有两年没有写博客了,回顾前两年,各种奔波,各种忙碌,也有不少的收获.从今天开始,我要把这些收获都分享在这里. 其实这两年,对我影响最大的是开发流程.总所周知,一个好的开发流程,对于项目的进行, ...
- iOS 小谈开发者中的个人、组织(公司、企业)账号
苹果对开发者主要分为3类:个人.组织(公司.企业).教育机构.即: 1.个人(Individual) 2.组织(Organizations) 组织类又分为2个小类: (1)公司(Company) (2 ...
- Http与Socket小谈
http与socket是网络编程中最为重要的概念,不管是客户端还是服务端,都是最为重要的部分,以下简述两者的关系和区别(个人见解). Http 定义 基于应用层的超文本传输协议.通常承载于TCP/IP ...
- 小谈 - web模仿手机打电话与正则表达式
昨天遇到了一个很棘手的问题,就是手机端调用web端的页面,如果用编辑器插入的内容页面中有电话的的数据就要变一下格式,让手机端可以实现拨号的功能. 研究了半天就是没一点头绪,但是偶尔看到数据中每一个电话 ...
- 小谈React、React Native、React Web
React有三个东西,React JS 前端Web框架,React Native 移动终端Hybrid框架,React Web是一个源码转换工具(React Native 转 Web,并之所以特别提出 ...
随机推荐
- Go 结构体方法
#### Go 结构体方法本来今天有些事情忙的不准备更新内容了,后来提前完成了, 所以还是要更新了; 毕竟坚持本就是一件不容易的事情!加油,相信不管是大家还是我,都有一些事情想要做,那就坚持吧,剩下的 ...
- 推荐一个github国内访问加速神器GitHub520
一.介绍 对 GitHub 说"爱"太难了:访问慢.图片加载不出来. 注: 本项目还处于测试阶段,仅在本机测试通过,如有问题欢迎提 issues 本项目无需安装任何程序,通过修改本 ...
- 如何通俗地理解docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...
- Nginx命令(全局配置文件与模块)
目录 一:Nginx命令 二:Nginx全局配置文件 1.nginx全局配置 2.过滤出Nginx 三:Nginx网址模块(解析) 一:Nginx命令 1.-v : 打印版本号 [root@web01 ...
- 免密码提交gitlab
在你的用户目录下新建一个文本文件.git-credentials echo 'https://henry:123456@ggithub.com' > /root/.git-credentials ...
- MySQL单表查询(分组-筛选-过滤-去重-排序)
目录 一:单表查询 1.单表查询(前期准备) 2.插入记录(写入数据) 3.查询关键字 二:查询关键字之where 1.查询id大于等于3小于等于6的数据 2.查询薪资是20000或者18000或者1 ...
- APC 篇—— APC 挂入
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...
- TensorFlow 入门 | iBooker·ApacheCN
原文:Getting Started with TensorFlow 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 不要担心自己的形象,只关心如何实现目标.--<原则>,生活原 ...
- 「JOI 2014 Final」飞天鼠
「JOI 2014 Final」飞天鼠 显然向上爬是没有必要的,除非会下降到地面以下,才提高到刚好为0. 到达一个点有两种情况:到达高度为0和不为0. 对于高度不为0的情况,显然花费的时间越少高度越高 ...
- Linq to SQL各种参考
原文:https://www.cnblogs.com/lyj/archive/2008/01/23/1049686.htmlhttps://www.cnblogs.com/lyj/archive/20 ...