C#提升(一、泛型)

一、什么是泛型

泛型,即“参数化类型”

我们来看以下代码,目的很明确,就是显示参数类型,这种类似的代码或者说只有参数类型不同,但是功能相同时,我们如何让代码写的更优雅?
C#提升(一、泛型)_第1张图片
在泛型没有出现的.Net FrameWork 1.0时代,可以这样来写:

C#提升(一、泛型)_第2张图片
我们来看这样子写的,确实更优雅了许多,但是这样子写会有两个问题,至于哪两个问题,看完全文你将得到答案
C#提升(一、泛型)_第3张图片
为了代码更加优雅,在.Net FrameWork 2.0时代,出现了泛型
在这里插入图片描述

二、泛型的种类

2.1 泛型类

C#提升(一、泛型)_第4张图片

2.2 泛型接口

C#提升(一、泛型)_第5张图片

2.3 泛型方法

C#提升(一、泛型)_第6张图片

2.4 泛型委托

在这里插入图片描述

三、泛型的继承

3.1 基类和接口

C#提升(一、泛型)_第7张图片

3.2 普通类

C#提升(一、泛型)_第8张图片

3.3 泛型类

C#提升(一、泛型)_第9张图片

四、泛型的约束

4.1 定义三个类使用

C#提升(一、泛型)_第10张图片

4.2 不使用泛型

在这里插入图片描述
C#提升(一、泛型)_第11张图片
可以看到 前两个正常打印,第三个抛异常,这就是object什么都可以传,导致的一个问题:传参不安全,很明显Japanese没有相对应的属性
在这里插入图片描述

4.3 使用泛型

可以看到这里我们对 输入进行的约束必须为People或其子类
C#提升(一、泛型)_第12张图片
所以,当我们再传Japanese时,直接提示不过
C#提升(一、泛型)_第13张图片

4.4 约束的种类

  1. 引用类型约束
    (T : class), 即T必须是一个引用类型。必须放在第一个。
  2. 值类型约束
    (T : struct) 。 必须放在第一个。
  3. 无参构造函数约束
    new() , 必须放在最后一个。
  4. 转换类型约束(基类约束、接口约束)
    class Sample where T : Stream
    class Sample where T1: T2 (如Sample
    class Sample where T : Stream, IEnumerable, IComparable 可以多个接口,但是只能一个class.

指定的类不能是结构,密封类比如string,或者这些特殊类型:
System.Object
System.Enum
System.ValueType
System.Delegate

五、泛型的性能

5.1 测试代码

定义三个方法
分别是直接类型、Object、泛型
C#提升(一、泛型)_第14张图片
每个方法循环1亿次,判定性能
C#提升(一、泛型)_第15张图片

5.2 测试结果

在这里插入图片描述
我们可以很清楚的看出
直接类型≈泛型

原因很明显
使用Object 涉及装箱和拆箱的过程
而泛型是延迟声明,使用的时候直接类型替换占位符,所以基本和直接类型性能一致

六、协变逆变

6.1 错误示范

C#提升(一、泛型)_第16张图片
在这里插入图片描述

6.2 协变

为了解决上述的问题,增加了协变的概念 ,在声明时增加out关键字,只能作为返回值使用
C#提升(一、泛型)_第17张图片
用它就可以这样写

IEnumerable<Bird> birds3 = new List<Bird>();
IEnumerable<Bird> birds4 = new List<Sparrow>();

C#提升(一、泛型)_第18张图片
委托可以这样写

Func<Bird> func = new Func<Bird>(() => null);
Func<Bird> func2 = new Func<Sparrow>(() => null);

6.3 逆变

逆变 :协变的逆过程,只能作为传参使用 关键字in
C#提升(一、泛型)_第19张图片

协变的逆过程

ICustomerIn<Sparrow> customerIn = new CustomerIn<Sparrow>();
ICustomerIn<Sparrow> customerIn2 = new CustomerIn<Bird>();

Action<Sparrow> action = new Action<Sparrow>((Sparrow i) => { });
Action<Sparrow> action2 = new Action<Bird>((Bird i) => { });

七、泛型的缓存

不同的类型在调用泛型时

  1. 每一个类型都会创建一份副本
  2. 每一个类型只会创建一次

你可能感兴趣的:(C#提升,c#,开发语言)