一、引入泛型
在实际开发中,常常会出现重复代码的问题,例如 。
文章插图
文章插图
运行结果
这里的三个方法,使用不同的类型干了同样的事情 。作为一个有追求的程序员,是绝不允许这样的事情发生的 。我们观察发现,这三个方法除了方法名称和参数类型不同,方法体一模一样 。我们知道object类型是一切类型的基类,根据里氏替换原则,子类对象可以赋值给父类,也即是说,可以使用object类型替换具体的类型 。于是有基类版本的通用方法,且看下图 。
文章插图
文章插图
运行结果
【C#笔记~泛型】代码重复的问题就这么轻松搞定,但是其中存在的问题却不容忽视 。
1.对于值类型(这里的int),发生了装箱、拆箱问题,从栈Copy到堆,从堆写到栈,都是多余的操作,产生性能损耗
2.object类型是一切类型的基类,那么这个方法对所有类型都适用,这样容易引发类型安全问题 。
那么,有没有一种方式,既可以解决代码重复问题,又可以避免出现上诉问题呢?
答案是:泛型 。
二、什么是泛型
泛型让我们可以编写一个可以与任何数据类型一起工作的类或方法 。可以简单地理解为:泛型是类型的模板 。
泛型不是一种语法糖,而是.NetFramework 2.0推出的新语法,是框架升级支持的新功能 。
三、声明和使用泛型
文章插图
泛型方法
文章插图
运行结果
泛型使用尖括号和泛型名称构成:<T>,使用时尖括号内的T需替换为实际类型,也可以不带尖括号而由类型推断判断实参的类型 。
四、泛型原理
在声明泛型时,类型是未确定的,在调用泛型时,必须指定实际类型 。这种在定义时未确定类型而使用时确定类型的方式,可以称为延迟声明 。延迟声明体现了推迟一切可以推迟的设计思想 。
文章插图
五、性能比较
文章插图
循环1亿次
文章插图
运行结果
多次运行后发现,普通方法和泛型方法的耗时相差不大,而object方法因为装箱耗时是其他两种方法的倍数 。
六、泛型类、泛型接口、泛型委托
前面我们讲解的都是泛型方法,其实除了泛型方法,还有泛型类、泛型接口、泛型委托 。
文章插图
泛型类
文章插图
泛型接口
文章插图
泛型委托
对于泛型类和泛型接口,如果其他类继承或实现了它,要求这个类必须指定具体的类型,或者不指定类型但此类也是泛型类 。
七、泛型约束
在第六点我们已经使用了泛型约束,请看上图where部分 。泛型约束是为类型安全而设计的,它有如下几种约束:
文章插图
结构约束 。值类型,必须在其他约束之前
文章插图
类约束 。引用类型,必须在其他类型约束之前
文章插图
无参数构造函数约束 。与其他约束使用时,必须放在最后
文章插图
基类约束 。基类或派生类,该基类必须是可继承的
文章插图
接口约束 。可以指定多个接口约束,类型必须实现该接口
八、协变(out)、逆变(in)
推荐阅读
- 一步步从头搭建 Vue 开发环境
- 清代三大女词人 清代国初第一词人
- 一款比phpmyadmin更好用的WEB数据库管理工具
- 北京供暖时间几月到几月份?
- 黑客大神谈一谈Linux与suid提权
- 南京一家三口被杀分尸 南京一家三口灭门案
- 药流一个月后昨晚尿床今天尿频
- 41天可以做药流吗
- 怀孕1个月可以药流吗
- 药流后残留25要清宫吗