网站首页 > 基础教程 正文
一、引入泛型
在实际开发中,常常会出现重复代码的问题,例如。
这里的三个方法,使用不同的类型干了同样的事情。作为一个有追求的程序员,是绝不允许这样的事情发生的。我们观察发现,这三个方法除了方法名称和参数类型不同,方法体一模一样。我们知道object类型是一切类型的基类,根据里氏替换原则,子类对象可以赋值给父类,也即是说,可以使用object类型替换具体的类型。于是有基类版本的通用方法,且看下图。
代码重复的问题就这么轻松搞定,但是其中存在的问题却不容忽视。
1.对于值类型(这里的int),发生了装箱、拆箱问题,从栈Copy到堆,从堆写到栈,都是多余的操作,产生性能损耗
2.object类型是一切类型的基类,那么这个方法对所有类型都适用,这样容易引发类型安全问题。
那么,有没有一种方式,既可以解决代码重复问题,又可以避免出现上诉问题呢?
答案是:泛型。
二、什么是泛型
泛型让我们可以编写一个可以与任何数据类型一起工作的类或方法。可以简单地理解为:泛型是类型的模板。
泛型不是一种语法糖,而是.NetFramework 2.0推出的新语法,是框架升级支持的新功能。
三、声明和使用泛型
泛型使用尖括号和泛型名称构成:<T>,使用时尖括号内的T需替换为实际类型,也可以不带尖括号而由类型推断判断实参的类型。
四、泛型原理
在声明泛型时,类型是未确定的,在调用泛型时,必须指定实际类型。这种在定义时未确定类型而使用时确定类型的方式,可以称为延迟声明。延迟声明体现了推迟一切可以推迟的设计思想。
五、性能比较
多次运行后发现,普通方法和泛型方法的耗时相差不大,而object方法因为装箱耗时是其他两种方法的倍数。
六、泛型类、泛型接口、泛型委托
前面我们讲解的都是泛型方法,其实除了泛型方法,还有泛型类、泛型接口、泛型委托。
对于泛型类和泛型接口,如果其他类继承或实现了它,要求这个类必须指定具体的类型,或者不指定类型但此类也是泛型类。
七、泛型约束
在第六点我们已经使用了泛型约束,请看上图where部分。泛型约束是为类型安全而设计的,它有如下几种约束:
八、协变(out)、逆变(in)
使用泛型之后,我们发现基类和子类的泛型并没有继承关系,但实际业务中,他们还是父子关系。
为解决上述问题,引入了协变、逆变。
1.协变,让赋值表达式右边可以用子类
协变只能修饰返回参数。为什么不能修饰传入参数呢?因为父类赋值给子类。
2.逆变,让赋值表达式右边可以用父类
逆变只能修饰传入参数。
3.协变逆变只能用于接口、委托。
猜你喜欢
- 2024-12-02 C++中的struct完全可以被class替代,为什么不删去它呢?
- 2024-12-02 C# 中 IsNullOrEmpty 和 IsNullOrWhiteSpace 你用对了吗?
- 2024-12-02 C#面试宝典 2022年 60个常见的C#面试问题和答案
- 2024-12-02 C#学习随笔—操作BIN文件(读,写,替代)
- 2024-12-02 C# 入门深度学习:万字长文讲解微积分和梯度下降
- 2024-12-02 344.C# 中的正则表达式:字符匹配、字面字符、特殊字符和转义序列
- 2024-12-02 C#通过二进制读写实现文件的伪加密
- 2024-12-02 C#移除字符串中的不可见Unicode字符
- 2024-12-02 使用 C# 解析月份简写的时间日期格式
- 2024-12-02 ILSpy借助reflexil修改C# DLL
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)