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 ...
随机推荐
- 第3章_关系数据库标准语言(SQL)_006_由元组关系演算到SQL Command_001_蕴含式 (其中有对EXISTS的分析)
前序的链接:元组关系演算 六. 蕴含式 ===>1. 什么是“蕴含式”===>设p.q为两个命题.复合命题“如果p,则q”称为p与q的蕴含式,记作p→q,并称p为蕴含式的前件,q为后件.定 ...
- Python Redis常用操作(持续更新)
目录 1.Redis简介 2.Redis部署 3.Redis API应用 4.String操作 1.Redis简介 redis是业界主流的key-value,nosql数据库之一.和Memcached ...
- ActiveMQ 反序列化漏洞(CVE-2015-5254)复现
1.运行漏洞环境 sudo docker-compose up -d 环境运行后,将监听61616和8161两个端口.其中61616是工作端口,消息在这个端口进行传递:8161是Web管理页面端口.访 ...
- 带你学够浪:Go语言基础系列-环境配置和 Hello world
文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 前面几周陆陆续续写了一些后端技术的文章,包括数据库.微 ...
- Linux (五) VIM编辑器
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.简介 Linux系统环境下的一款非常重要的文本编辑工具,我们在Linux环境下几乎所有的文本文件 ...
- Java实现 LeetCode 728 自除数(暴力)
728. 自除数 自除数 是指可以被它包含的每一位数除尽的数. 例如,128 是一个自除数,因为 128 % 1 == 0,128 % 2 == 0,128 % 8 == 0. 还有,自除数不允许包含 ...
- Java实现 蓝桥杯 算法训练 关联矩阵
算法训练 关联矩阵 时间限制:1.0s 内存限制:512.0MB 提交此题 问题描述 有一个n个结点m条边的有向图,请输出他的关联矩阵. 输入格式 第一行两个整数n.m,表示图中结点和边的数目.n&l ...
- Java实现 蓝桥杯VIP 算法训练 新生舞会
问题描述 新生舞会开始了.n名新生每人有三个属性:姓名.学号.性别.其中,姓名用长度不超过20的仅由大小写字母构成的字符串表示,学号用长度不超过10的仅由数字构成的字符串表示,性别用一个大写字符'F' ...
- Java实现 蓝桥杯VIP 算法训练 比赛安排
问题描述 设有有2 n(n<=6)个球队进行单循环比赛,计划在2 n – 1天内完成,每个队每天进行一场比赛.设计一个比赛的安排,使在2 n – 1天内每个队都与不同的对手比赛. 输入格式 输入 ...
- Java中map.getOrDefault()方法的使用
Map.getOrDefault(Object key, V defaultValue)方法的作用是: 当Map集合中有这个key时,就使用这个key值: 如果没有就使用默认值defaultV ...