C# 什么是泛型 ?以及对泛型各方面的一些知识点的整理
1.1 理解什么是泛型
在.NET 2.0,可以成为革命性壮举的, 就是引入了激动人心的特性——泛型。.NET泛型是CLR和高级语言共同支持的一种全新的结构,实现了一种将类型抽象化的通用处理方式。在泛型机制中,我们不再为特定的类型而编码,取而代之的是一种通用的编码方式,因此泛型本质上就是一种代码重用。这种代码重用并非面向对象中通过集成、集合、多态等方式实现;而是实现为一般化、可重用的算法抽象,但在执行效率上与执行特定类型相同。
1.2 理解泛型的优点
泛型增强了代码的可读性,将大量的安全检查从执行期转移到编译期,从而提高代码的安全性和性能。从根本上来说,泛型实现了类型和方法的参数化。
1.3 理解泛型类
- C#自定义泛型类用得最广泛,就是集合(Collection)中。实际上,泛型的产生其中一个原因就是为了解决原来集合类中元素的装箱和拆箱问题。由于泛型的使用,使得集合内所有元素都属于同一类,这就把类型不同的隐患消灭在编译阶段——如果类型不对,则编译错误。
- 泛型的初始化:泛型是需要进行初始化的。使用T doc = default(T)以后,系统会自动为泛型进行初始化。
- 定义一个泛型类和定义非泛型类没有没有太大的区别,而主要的不同在于:类型参数化。类型定义时,将指定类型参数(Type Parameter,通常以T 表示),紧随类名,并包含在<>符号内。对于这种具有类型参数的类型,我们称其为:开放式类型;而对于为类型参数传入实际参数的类型,被称为:封闭式类型
1.4 理解泛型方法
- 在C#2.0中,方法可以定义特定于其执行范围的泛型参数。
- 泛型方法,提供了更加多变的灵活性。泛型方法可以存在于泛型类,也可以在于非泛型类中。你可以将类型参数作为某个方法的参数、返回值、或者局部变量,该类型参数可能并不被整个类所需要,而更明确的用于某个方法。
例如:
1.5 理解泛型接口
CLR 同样提供了对泛型接口的支持,在.NET 集合类中就实现了多个泛型接口,例如IList<T> 泛型接口的实现可以表示为:

在.NET 框架类库中的泛型接口,还包括 ICollection<T>、Icomparable<T>、Icomparer<T>、IDictionary<Tkey,TValue>等等。
1.6 理解泛型约束
约束,指在定义泛型类时,对于能够用于实例化参的类型所做的限制,这种限制能够保证类型参数局限在一定的目标范围,以实现在泛型类中的方法或者运算符能够得到类型参数的支持而不会引起其他问题。这种限制正是通过一个或者多个约束来获得,而约束则是通过where子句来实现的,多个约束之间以逗号隔开。
约束主要包括:构造器约束、值类型约束、引用类型约束、基类约束、接口约束等。
- T : new() ,表示类型参数必须具有公共无参构造函数,有多个约束存在时,必须将new()约束置于最后。
- T : struct ,表示类型参数必须是值类型。
- T : class ,表示类型参数必须是引用类型,显示class和struct不能同时指定。
- T : 基类名,表示类型参数必须是基类及其派生类型,例如 T : Student。但是不能既指定约束基类,又指定class。
- T : 接口名,表示类型参数必须是指定的接口或者实现了该接口的接口,可以定义多个接口约束,同时约束接口也可以是泛型的。
- 泛型约束,提供了更强的类型检查,并且更加有效的参数类型有时能够减少不必要的类型转换而改进性能。但是另外一方面,强制性的约束可能使得算法重用的功能受到限制。
1.7 理解泛型使用场景及作用
- 在泛型机制中,我们不再为特定的类型而编码,取而代之的是一种通用的编码方式,因此泛型本质上就是一种代码重用。这种代码重用并非面向对象中通过集成、集合、多态等方式实现;而是实现为一般化、可重用的算法抽象,但在执行效率上与执行特定类型相同。
- 泛型增强了代码的可读性,将大量的安全检查从执行期转移到编译期,从而提高代码的安全性和性能。从根本上来说,泛型实现了类型和方法的参数化。
1.8 理解泛型的可变性-协变性和逆变性
可变性是以一种类型安全的方式,将一个对象当做另一个对象来使用。如果不能将一个类型替换为另一个类型,那么这个类型就称之为:不变量。协变和逆变是两个相互对立的概念:
- 如果某个返回的类型可以由其派生类型替换,那么这个类型就是支持协变的
- 如果某个参数类型可以由其基类替换,那么这个类型就是支持逆变的。
在C# 4.0之前,所有的泛型类型都是不变量——即不支持将一个泛型类型替换为另一个泛型类型,即使它们之间拥有继承关系,简而言之,在C# 4.0之前的泛型都是不支持协变和逆变的。
2.1 泛型概述
1.1.1 泛型广泛用于容器(collections)
1.1.2 命名空间System.Collections.Generic
2.2 泛型的优点.
以前类型的泛化(generalization)是靠类型与全局基类System.Object的相互转换来实现。.
NET框架基础类库的ArrayList容器类,就是这种局限的一个例子。ArrayList是一个很方便的容器类,使用中无需更改就可以存储任何引用类型或值类型
2.3 泛型类型参数.
在泛型类型或泛型方法的定义中,类型参数是一个占位符(placeholder),通常为一个大写字母,
如T。在客户代码声明、实例化该类型的变量时,把T替换为客户代码所指定的数据类型。泛型类,如泛型概述中给出的MyList<T>类,
不能用作as-is,原因在于它不是一个真正的类型,而更像是一个类型的蓝图。要使用MyList<T>,
客户代码必须在尖括号内指定一个类型参数,来声明并实例化一个已构造类型(constructed type)。这个特定类的类型参数可以是编译器识别的任何类型
2.4 类型参数的约束.
若要检查表中的一个元素,以确定它是否合法或是否可以与其他元素相比较,
那么编译器必须保证:客户代码中可能出现的所有类型参数,都要支持所需调用的操作或方法。这种保证是通过在泛型类的定义中,应用一个或多个约束而得到的。
一个约束类型是一种基类约束,它通知编译器,只有这个类型的对象或从这个类型派生的对象,可被用作类型参数。一旦编译器得到这样的保证,它就允许在泛型类中调用这个类型的方法
2.5 泛型类.
泛型类封装了不针对任何特定数据类型的操作。
泛型类常用于容器类,如链表、哈希表、栈、队列、树等等。这些类中的操作,如对容器添加、删除元素,不论所存储的数据是何种类型,都执行几乎同样的操作
2.6 泛型接口.
不论是为泛型容器类,还是表示容器中元素的泛型类,定义接口是很有用的。
把泛型接口与泛型类结合使用是更好的用法,比如用IComparable<T>而非IComparable,以避免值类型上的装箱和拆箱操作。.
NET框架2.0类库定义了几个新的泛型接口,以配合System.Collections.Generic中新容器类的使用
2.7 泛型方法.
1.7.1泛型方法参数声明
1.7.2泛型方法重载
1.7.3泛型方法约束
2.8 泛型委托.
论是在类定义内还是类定义外,委托可以定义自己的类型参数。
引用泛型委托的代码可以指定类型参数来创建一个封闭构造类型,这和实例化泛型类或调用泛型方法一样
2.9 泛型代码中的default 关键字.
在泛型类和泛型方法中会出现的一个问题是,如何把缺省值赋给参数化类型,此时无法预先知道以下两点:
- T将是值类型还是引用类型
- 如果T是值类型,那么T将是数值还是结构
对于一个参数化类型T的变量t,仅当T是引用类型时,t = null语句才是合法的; t = 0只对数值的有效,而对结构则不行。
这个问题的解决办法是用default关键字,它对引用类型返回空,对值类型的数值型返回零。而对于结构,它将返回结构每个成员,并根据成员是值类型还是引用类型,返回零或空
3.10 C++ 模板和C# 泛型的区别. (知识拓展)
C# Generics and C++ templates are both language features that provide support for parameterized types. However, there are many differences between the two. At the syntax level, C# generics are a simpler approach to parameterized types without the complexity of C++ templates. In addition, C# does not attempt to provide all of the functionality that C++ templates provide. At the implementation level, the primary difference is that C# generic type substitutions are performed at runtime and generic type information is thereby preserved for instantiated objects.
3.11 运行时中的泛型.
当泛型类或泛型方法被编译为微软中间语言(MSIL)后,它所包含的元数据定义了它的类型参数。根据所给的类型参数是值类型还是引用类型,对泛型类型所用的MSIL也是不同的。
当第一次以值类型作为参数来构造一个泛型类型,运行时用所提供的参数或在MSIL中适当位置被替换的参数,来创建一个专用的泛型类型。[JX3]
1.1 基础类库中的泛型.
|
泛型类或接口 |
描述 |
对应的非泛型类型 |
|
Collection<T> ICollection<T> |
为泛型容器提供基类 |
CollectionBase ICollection |
|
Comparer<T> IComparer<T> IComparable<T> |
比较两个相同泛型类型的对象是否相等、可排序。 |
Comparer IComparer IComparable |
|
Dictionary<K, V> IDictionary<K,V> |
表示用键组织的键/值对集合。 |
Hashtable IDictionary |
|
Dictionary<K, V>.KeyCollection |
表示Dictionary<K, V>中键的集合。 |
None. |
|
Dictionary<K, V>.ValueCollection |
表示Dictionary<K, V>中值的集合。 |
None. |
|
IEnumerable<T> IEnumerator<T> |
表示可以使用foreach 迭代的集合。 |
IEnumerable IEnumerator |
|
KeyedCollection<T, U> |
表示有键值的集合。 |
KeyedCollection |
|
LinkedList<T> |
表示双向链表。 |
None. |
|
LinkedListNode<T> |
表示LinkedList<T>中的节点。 |
None. |
|
List<T> IList<T> |
使用大小可按需动态增加的数组实现 IList 接口 |
ArrayList IList |
|
Queue<T> |
表示对象的先进先出集合。 |
Queue |
|
ReadOnlyCollection<T> |
为泛型只读容器提供基类。 |
ReadOnlyCollectionBase |
|
SortedDictionary<K, V> |
表示键/值对的集合,这些键和值按键排序并可按照键访问,实现IComparer<T>接口。 |
SortedList |
|
Stack<T> |
表示对象的简单的后进先出集合。 |
Stack |
C# 什么是泛型 ?以及对泛型各方面的一些知识点的整理的更多相关文章
- Java 泛型 Java使用泛型的意义
Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...
- C#非泛型集合和泛型集合的超级详解
C# 泛型集合之非泛型集合类与泛型集合类的对应: ArrayList对应List HashTable对应Dictionary Queue对应Queue Stack对应Stack SortedList对 ...
- 重读《深入理解Java虚拟机》六、Java泛型 VS C#泛型 (伪泛型 VS 真泛型)
一.泛型的本质 泛型是参数化类型的应用,操作的数据类型不限定于特定类型,可以根据实际需要设置不同的数据类型,以实现代码复用. 二.Java泛型 Java 泛型是Java1.5新增的特性,JVM并不支持 ...
- Java泛型总结——吃透泛型开发
什么是泛型 泛型是jdk5引入的类型机制,就是将类型参数化,它是早在1999年就制定的jsr14的实现. 泛型机制将类型转换时的类型检查从运行时提前到了编译时,使用泛型编写的代码比杂乱的使用objec ...
- 自定义泛型_无多态_通配符无泛型数组_jdk7泛型使用
通配符 T, K, V, E 等泛型字母为有类型, 类型参数赋予具体的值 ? 未知类型 类型参数赋予不确定值, 任意类型 只能用在 声明类型上,方法参数上, 不能用在定义泛型类上 上限 extends ...
- Java中泛型区别以及泛型擦除详解
一.引言 复习javac的编译过程中的解语法糖的时候看见了泛型擦除中的举例,网上的资料大多比较散各针对性不一,在此做出自己的一些详细且易懂的总结. 二.泛型简介 泛型是JDK 1.5的一项新特性,一种 ...
- C#非泛型集合类与泛型集合类的区别 (转)
来自:http://blog.csdn.net/jiayanhui2877/article/details/7623845 C# 泛型集合之非泛型集合类与泛型集合类的对应: ArrayList对应Li ...
- .NET泛型与非泛型的问题
泛型集合通常情况下,建议您使用泛型集合,因为这样可以获得类型安全的直接优点而不需要从基集合类型派生并实现类型特定的成员.下面的泛型类型对应于现有的集合类型:1.List 是对应于 ArrayList ...
- 泛型与非泛型集合类的区别及使用例程,包括ArrayList,Hashtable,List<T>,Dictionary<Tkey,Tvalue>,SortedList<Tkey,Tvalue>,Queue<T>,Stack<T>等
泛型与非泛型集合类在C#程序中是非常重要的一个基础概念,这里列一个表来进行对比: 非泛型集合类 泛型集合类 描述 ArrayList List<T> 表示具有动态大小的对象数组 Hasht ...
随机推荐
- C#中的List基础用法汇总
List类是ArrayList类的泛型等效类,该类使用大小可按需动态增加的数组实现IList泛型接口. 泛型的好处:它为使用c#语言编写面向对象程序增加了极大的效力和灵活性.不会强行对值类型进行装箱和 ...
- Leetcode 416分割等和子集
416. 分割等和子集 已知是个背包问题,由于可以等分为两部分,所以必定是个偶数. 一开始想到的是回溯法 bool helper(vector<int>&nums, int i, ...
- React Router简单Demo
简介 react router是使用react的时候首选的一个路由工具. 安装 react router包含react-router,react-router-dom和react-router-nat ...
- 【HIVE】(3)联合查询join、时间戳函数、字符串函数
数据 t_join1.txt 1,a,1 2,b,2 3,c,4 t_join2.txt 1,2a 2,2b 3,2c 建表.导入: create table t_join1(id int, name ...
- JAVASE(十五) 泛型 :泛型用例、自定义泛型类、通配符
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.泛型在集合中的使用 1.1 在集合中使用泛型之前的例子 为什么要有泛型(Generic)? 1. ...
- Java实现 LeetCode 795 区间子数组个数 (暴力分析)
795. 区间子数组个数 给定一个元素都是正整数的数组A ,正整数 L 以及 R (L <= R). 求连续.非空且其中最大元素满足大于等于L 小于等于R的子数组个数. 例如 : 输入: A = ...
- (Java实现) 洛谷 P1691 有重复元素的排列问题
题目描述 设R={r1,r2,--,rn}是要进行排列的n个元素.其中元素r1,r2,--,rn可能相同.使设计一个算法,列出R的所有不同排列. 给定n以及待排列的n个元素.计算出这n个元素的所有不同 ...
- Java实现 蓝桥杯 算法训练 约数个数
算法提高 约数个数 时间限制:1.0s 内存限制:512.0MB 输入一个正整数N (1 样例输入 12 样例输出 6 样例说明 12的约数包括:1,2,3,4,6,12.共6个 import jav ...
- Java实现 LeetCode 164 最大间距
164. 最大间距 给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值. 如果数组元素个数小于 2,则返回 0. 示例 1: 输入: [3,6,9,1] 输出: 3 解释: 排序后的数组是 ...
- Java实现 LeetCode 73 矩阵置零
73. 矩阵置零 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [ [1,1,1], [1,0,1], [1,1,1] ...