作者 | 羽生结弦

责编 | 胡巍巍

在开发过程中,同一段代码处出现多次调用,并且会有不同的类型在使用,这种就叫做跨类型代码复用。一般情况下跨类型代码复用我们会用到如下两种方法:

1. 继承;

2. 泛型。

继承是通过父类来代表代码复用,而泛型是通过带有占位符的模板来代码复用,其中占位符指的是类型。

比如:int、syting和实体等。本片主要讲解泛型的相关知识,下面就来详细讲解一下泛型。

零、泛型类型

泛型会声明类型参数,消费者需要提供类型参数来把占位符类型填充上。我们先来看一个例子:

在上面的代码中当我们将string传入泛型类中,将会隐式动态的创建类型,这种操作被称为合成,合成将发生在运行时,而非编译时。当我们在代码中传入非string类型的值时,在编译时将报错。同样在上面的代码中我们也看到了int传入泛型类中的情况,这就说明泛型类可以跨类型复用。

小知识1:

我们将GenericClass<T>称为开放类型(OpenType),而将GenericClass<string>称为封闭类型(CloseType),开放类型在编译后就变成了封闭类型,在运行时所有的泛型类型都是封闭类型,因为占位符已经被具体类型填充完毕。

小知识2:

对于每一种封闭类型,静态数据都是唯一的,例如:

上面代码中,MyClass中存在一个静态字段Count,我们看到前两次的调用输出的分别是1和2,但是第三次输出的确实1,那么这是为什么呢,原因就是前两次的类型参数和泛型类型种的静态字段的类型一致,而第三次的类型参数不一致导致的。

在泛型类型饿子类中可以继续让父类参数保持开放,也剋及关闭父类的类型参数,同样子类也可以引入新的类型,我们来看一下例子:

小知识:

封闭参数类型的时候,该类型可以把自己作为具体的类型,例子如下:

泛型方法

泛型方法在方法签名内声明类型参数,例如下:

在上面的代码中我们看到 ```generic.GenericFun<int>(12,4);``` ,我们将int传入泛型方法中,现在我们将这行代码改写成如下形式 ```generic.GenericFun(12,4);```。

我们发现现在这段代码和前面那段代码缺少了 <int> ,那么这么写代码是否有错呢?

答案是要看情况,当编译器可以推断出参数类型的话,我们可以省略掉参数类型,但是当编译器无法推断出参数类型的话我们就必须写上参数类型了。

当然上面这段代码是可以正确运行的,因为编译器可以正确的推断出参数类型。
我们还有如下几点需要注意的:

1. 泛型类中的方法,如果方法引入了参数类型,那它就是泛型方法,反之就不是泛型方法;

2. 除了class、struct、interface、delegate 和方法可以引入类型参数外,属性、字段、索引器、事件和构造函数等都不能声明类型参数,但是可以使用所在泛型类的类型参数。

小知识:

泛型类型和泛型方法可以有多个参数类型,例如 ```class a<T,U>``` 调用方法和单个参数类型一样。结合这一点我们就可以推断出泛型类型和泛型方法可以出现重载,只要参数类型的数量不同就没问题。

在一些情况下我们需要获取参数类型的默认值,这时我们就可以使用default(T)来获得。

约束

我们虽然可以使用所有类型作为泛型类型参数,但是我们在实际开发时很少会这么使用,一般会将类型参数约束到指定的范围内。泛型可用约束如下:

1. base-class:某一个父类的子类;

2. interface:必须是实现了指定的接口;

3. class:必须是引用类型;

4. struct:必须是非空值类型;

5. new():必须包含无参构造函数;

6. U:T:U必须继承T

我们使用的时候是这样的:

上面的代码表示 Generic1 类的参数类型T继承自Aclass,Generic2 类的T继承子Aclass,并且实现了 Binterface 接口,而且U包含了无参构造函数。

注意:约束可以用于泛型类型和泛型方法

类型参数与转换

C#种转换支持如下几种:

1. 数值转换;

2. 引用转换;

3. 装箱拆箱转换;

4. 自定义转换。

在发生编译的时候,会根据一直类型的操作数来决定采用那种转换,但是在泛型中我们不知道具体的类型是什么,编译器就会默认使用自定义转换,那么就有可能出现错误。

为了解决这个问题,我们引入了as ,例如我们将传进来的值转换成StringBuilder,这时我们可以这么做:

variance 转换

讲解variance 转换前,先来简单了解一下协变、逆变和不变。

1. 协变(Covariance):当T作为返回值输出的时候;

2. 逆变(Contravariance):当T作为输出值的时候;

3. 不变(Invariance):当T即是输入又是输出时。

注意:以上这三种就是variance,只能用在接口和委托中。

所谓variance 转换就是上面三种之间的相互转换,variance 转换是引用转换的一个方法,从a转换到b如果是本体转换或者隐式引用转换,那么就是正确的。例如:

作者简介:朱钢,笔名羽生结弦,CSDN博客专家,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司,从事企业级安全监控系统的开发。

人工智能学习路线+实战训练

https://edu.csdn.net/topic/ai30?utm_source=csdn_bw

【END】

 热 文 推 荐 

☞华人学者解开计算机领域 30 年难题:布尔函数敏感度猜想

☞百度移动:静悄悄的战争

☞三十年软件开发之路:老码农的自我修养!

☞Android 告急!

3个核心差异, 告诉你为什么Libra永远成不了比特币!

微博宕机复盘:什么样的技术架构,可支持80个明星并发出轨?

☞公开课 | 详解事件抽取与事件图谱构建

超酷炫!Facebook用深度学习和弱监督学习绘制全球精准道路图

中国第一程序员,微软得不到他就要毁了他!

点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

你点的每个“在看”,我都认真当成了喜欢

看完这篇,终于知道自己会不会 C# 泛型了!相关推荐

  1. 【算法入门】用Python手写五大经典排序算法,看完这篇终于懂了!

    算法作为程序员的必修课,是每位程序员必须掌握的基础.作为Python忠实爱好者,本篇将通过Python来手撕5大经典排序算法,结合例图剖析内部实现逻辑,对比每种算法各自的优缺点和应用点.相信我,耐心看 ...

  2. 用Python手写五大经典排序算法,看完这篇终于懂了!

    算法作为程序员的必修课,是每位程序员必须掌握的基础.作为Python忠实爱好者,本篇东哥将通过Python来手撕5大经典排序算法,结合例图剖析内部实现逻辑,对比每种算法各自的优缺点和应用点.相信我,耐 ...

  3. 【JVM系列3】方法重载和方法重写原理分析,看完这篇终于彻底搞懂了

    深入分析Java虚拟机中方法执行流程及方法重载和方法重写原理 前言 思考 栈帧 局部变量表(Local Variables) 操作数栈(Operand Stacks) 动态连接(Dynamic Lin ...

  4. 手机芯片里的NPU到底是什么?看完这篇终于懂了

    21世纪初的科幻电影中,AI总是作为机器人的形象出现,电影中的人工智能几乎"无所不能",用脑洞大开的想象力为我们演绎充满科技感的未来世界.不过回到现实世界,AI虽然还没有实现科幻大 ...

  5. string 引用没有设置为 string 的实例。 参数名: s_Java中的值传递和引用传递,看完这篇终于终于明白了!...

    当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参数.当一个对象实例作为一个参数 ...

  6. 看完这篇文章之后,终于明白了编译到底怎么回事。

    看完这篇文章之后,终于明白了编译到底怎么回事. 1 对于同一个语句,有如下三种:高级语言.低级语言.机器语言的表示 C语言  a=b+1; 汇编语言  mov -0xc(%ebp),%eax add ...

  7. 看完这篇文章之后,终于明白了编译到底怎么回事

    看完这篇文章之后,终于明白了编译到底怎么回事. 1 对于同一个语句,有如下三种:高级语言.低级语言.机器语言的表示 C语言  a=b+1; 汇编语言  mov -0xc(%ebp),%eax add ...

  8. 我就不信看完这篇你还搞不懂信息熵

    我就不信看完这篇你还搞不懂信息熵 https://mp.weixin.qq.com/s/7NrB0UtmELXD3UNO3C6jGA 让我们说人话!好的数学概念都应该是通俗易懂的. 信息熵,信息熵,怎 ...

  9. 互联网黑话最全收录|还在说大白话?看完这篇包你成为职场“社牛”

    文章目录 互联网黑话是怎么产生的? 互联网黑话是好是坏? 互联网黑话入门级教学指南 写在最后 刚刚加入字节时,比起高强度.快节奏的工作,最先迎面而来的不适应居然是--沟通障碍! "你说这话的 ...

  10. 神了!!看完这篇文章我不仅学会了手撸vue三开关组件,还搞懂了父子组件传值

    神了!!看完这篇文章我不仅学会了手撸vue三开关组件,还搞懂了父子组件传值 引子 前置知识 什么是vue组件 父子组件传值 父传子 子传父 model选项的引入 三开关组件(three-switch) ...

最新文章

  1. Spring中自动装配的方式有哪些?
  2. 样本距离计算、向量范数、矩阵范数
  3. Odoo (OpenERP/TinyERP)-10.0 (Debian 8)
  4. python爬虫能秒杀么_面试题之用python爬取并夕夕不同时段秒杀商品信息
  5. js 删除服务器文件,Node.js复制/删除服务器端文件到指定目录文件夹下,并且预判是否存在该目录,如果没有,则递归创建该文件夹目录...
  6. Java系列之雪花算法和原理
  7. vba 保存word里面的图片_笔记7 【office精华课】一套课程学会Word+Excel+PPT(一)【Word】(2020年第37周 周五)...
  8. 三年级小孩近视150度需要戴近视眼镜么?
  9. web网页设计实例作业 我的家乡- 达州(4页) HTML+CSS+JavaScript dreamweaver作业静态HTML网页设计模板
  10. 计算机语言安装不上,安装程序包的语言不受系统支持该怎么办?解决方法教程...
  11. android 4.4 java版本_Android4.0-4.4 加入实体按键振动支持的方法(java + smali版本号)
  12. Acorn Mac 7.1.1
  13. Visual Studio 默认编码为 utf-8
  14. windpy 连接数据库_python怎么连wind数据库
  15. 像滴滴快车一样的网约车上区块链后能否杜绝惨案发生
  16. 关于 四舍六入五成双/四舍六入五留双/四舍六入五单双 等口诀的实例研究
  17. LeetCode题解:寻找比目标字母大的最小字母
  18. unity音乐计算机谱子,Unity钢琴简谱-数字双手-Alan Walker
  19. Python中mask使用
  20. 蚂蚁金服大规模分布式事务实践和开源详解

热门文章

  1. kubenetes 1.4安装kube-UI
  2. 《SQL高级应用和数据仓库基础(MySQL版)》作业 ·007
  3. 低配本用win10服务器系统,低配电脑装win10最早版可以吗
  4. esp8266 eeprom_ESP8266_08基于flash的数据掉电保护
  5. java jsp动作_Java中级—JSP九大内置对象和动作
  6. Linux的iovec、readv和writev
  7. Material Design基础
  8. 水力压裂化学品行业调研报告 - 市场现状分析与发展前景预测
  9. 中国口内X射线系统行业市场供需与战略研究报告
  10. java怎样才算高级_怎样才算是一名java高手?