CLR via c#读书笔记八:泛型
1、定义泛型类型或方法时,为类型指定的任何变量(比如T)都称为类型参数。使用泛型类型或方法时指定的具体数据类型称为类型实参。
2、System.Collections.Concurrent命名空间提供了线程安全的泛型集合类。Microsoft建议使用泛型集合类,不建议使用非泛型集合类。
3、具有泛型类型参数的类型称为开放类型,CLR禁止构造开放类型的任何实例。这类似于CLR禁止构造接口类型的实例。代码引用泛型类型时可指定一组泛型类型实参。为所有类型参数都传递了实际的数据类型,类型就成为封闭类型。CLR允许构造封闭类型的实例。
4、每个封闭类型都有自己的静态字段。换言之,假如List<T>定义了任何静态字段,这些字段不会在一个List<DateTime>和一个List<String>之间共享;每个封闭类型对象都有自己的静态字段。
5、泛型类型定义静态构造器的目的是保证传递的类型实参满足特定条件。例如,我们可以向下面这样定义只能处理枚举类型的泛型类型:
- internal sealed class GenericTypeThatRequiresAnEnum<T>{
- static GenericTypeThatRequiresAnEnum(){
if(!typeof(T).IsEnum){
throw new ArgumentException("T must be an enumerated type");
}
}- }
CLR提供了名为约束的功能,可以更好的指定有效的类型参数。遗憾的是,约束无法将类型实参限制为“仅枚举类型”。正是因为这个原因,所以上例需要用静态构造器来保证类型是一个枚举类型。
6、泛型类型仍然是类型,所有能从其他任何类型派生。使用泛型类型指定类型实参时,实际是在CLR中定义一个新的类型对象,新的类型对象从泛型类型派生自的那个类型派生。
7、泛型类型同一性:C#允许使用简化的语法来引用泛型封闭类型,同时不会影响类型的相等性,类如:
- using DateTimeList=System.Collections.Generic.List<System.DateTime>;
using指令实际定义的是名为DateTimeList的符号,代码编译时,编译器将代码中出现的所有DateTimeList替换成System.Collections.Generic.List<System.DateTime>。这样就允许开发人员使用简化的语法,同时不影响代码的实际含义。
8、CLR要为每种不同的方法/类型组合生成本机代码。这个现象称为代码爆炸。幸好,CLR内建了一些优化措施能缓解代码爆炸。首先,假如为特定的类型实参调用了一个方法,以后再用相同的类型实参调用这个方法,CLR只会为这个方法/组合编译一次代码,同一个AppDomain中能共享不同程序集编译的相同泛型类型。另一个优化,它认为所有引用类型实参都完全相同,所以代码能够共享。例如,CLR为List<String>的方法编译的代码可直接用于List<Stream>的方法,因为String和Stream均为引用类型。事实上,对于任何引用类型,都会使用相同的代码,CLR之所以能执行这个优化,是因为所有引用类型的实参和变量实际只是指向堆上对象的指针(32位系统上是32位指针,64位系统上是64位指针),而所有对象指针都以相同方式操纵。但是类型实参是值类型,CLR 就必须专门为那个值类型生成本机代码。因为值类型的大小不定。
9、泛型接口
10、泛型委托
CLR支持泛型委托,目的是保证任何类型的对象都能以类型安全的方式传给回调方法。此外,泛型委托允许值类型实例在传给回调方法时不进行任何装箱。
11、委托和接口的逆变和协变泛型类型实参
不变量(invariant)意味着泛型类型参数不能更改。
逆变量(contravariant)意味着泛型类型参数可以从一个类更改为它的某个派生类。在C#是用in关键字标记逆变量形式的泛型类型参数。逆变量泛型类型参数只出现在输入位置,比如作为方法的参数。
协变量(covariant)意味着泛型类型参数可以从一个类更改为它的某个基类。c#是用out关键字标记协变量形式的泛型类型参数。协变量泛型类型参数只能出现在输出位置,比如作为方法的返回类型。
12、泛型方法
CLR还允许方法指定它自己的类型参数。这些类型参数可以作为参数、返回值和局部变量的类型使用。
- internal sealed class GenericType(T){
- private T m_value;
public GenericType(T value){ m_value=value; }
public TOutput Converter<TOutput>(){
- TOutput result=(TOutput)Convert.ChangeType(m_value,typeof(TOutput));
return result;//返回类型转换之后的结果
- }
- }
这个例子类型参数是T,方法定义了自己的类型参数TOutput。
13、可验证性和约束
约束
- public static T Min<T>(T o1,T o2) where T:IComparable<T>{
- if(o1.CompareTo(o2)<0) return o1;
return o2;- }
C#的where关键字告诉编译器,为T指定的任何类型都必须实现同类型(T)的泛型IComparable接口。
重写虚泛型方法时,重写的方法必须指定相同数量的类型参数,而且这些类型参数会继承在基类方法上指定的约束。事实上,根本就不允许为重写方法的类型参数指定任何约束。但类型参数的名称是可以改变的。
14、主要约束
类型参数可以指定零个或者一个主要约束。主要约束可以是代表非密封类的一个引用类型。不能指定一下特殊引用类型:System.Object,System.Array,System.Delegate,System.multicastDelegate,System.ValueType,System.Enum或者System.Void。
指定引用类型约束,相当于向编译器承诺:一个指定的类型实参要么是与约束类型相同的类型,要么是从约束类型派生的类型。
有两个特殊的主要约束:class和struct。其中,class约束向编译器承诺类型实参是引用类型。任何类型、接口类型、委托类型或者数组类型都满足这个约束。struct约束向编译器承诺类型实参是值类型。
15、所有值类型都隐式地有一个公共无参构造器。
16、次要约束
类型参数可以指定零个或者多个次要约束,次要约束代表接口类型。
还有一个次要约束成为类型参数约束,有时也称为裸类型约束。它允许一个泛型类型或方法规定:指定的类型实参要么是约束的类型,要么是约束的类型的派生类。
17、构造器约束
类型参数可指定零个或一个构造器约束,它向编译器承诺类型实参是实现了公共无参构造器的非抽象类型。
- internal sealed class ConstructorConstraint<T> where T:new(){
- public static T Factory(){
- //允许,因为所有值类型都隐式有一个公共无参构造器。
- //而如果指定的是引用类型,约束也要求它提供公共无参构造器
- return New T();
- }
- }
CLR via c#读书笔记八:泛型的更多相关文章
- [Clr via C#读书笔记]Cp12泛型
Cp12泛型 Generic: 特点 源代码保护 类型安全 清晰代码 更佳性能 Framework中的泛型 System.Collections.Generic; 开放类型,封闭类型:每个封闭类型都有 ...
- 《CLR via C#》读书笔记 之 泛型
第十二章 泛型 2014-06-15 初始泛型 12.3 泛型基础结构 12.3.1 开放类型与封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码爆炸 12.6 ...
- CLR via C# 读书笔记---常量、字段、方法和参数
常量 常量是值从不变化的符号.定义常量符号时,它的值必须能在编译时确定.确定后,编译器将唱两只保存在程序集元数据中.使用const关键字声明常量.由于常量值从不变化,所以常量总是被视为类型定义的一部分 ...
- CLR via C# 读书笔记-21.托管堆和垃圾回收
前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...
- CLR via c#读书笔记九:接口
1.接口对一组方法签名进行了统一命名.接口还能定义事件.无参属性和有参属性(C#的索引器). 2.c#禁止接口定义任何一种静态成员. 3.C#编译器要求将实现接口的方法标记为public.CLR要求将 ...
- CLR via #C读书笔记三:基元类型、引用类型和值类型
1.一些开发人员说应用程序在32位操作系统上运行,int代表32位整数:在64位操作系统上运行,int代表64位整数.这个说法是完全错误的.C#的int始终映射到System.Int32,所以不管在什 ...
- Effective Java 读书笔记之四 泛型
泛型的本质是参数化类型.只对编译器有效. 一.请不要在新代码中使用原生态类型 1.泛型类和接口统称为泛型,有一个对应的原生态类型. 2.原生类型的存在是为了移植兼容性. 3.无限制通配类型和原生态类型 ...
- Clr Via C#读书笔记---I/O限制的异步操作
widows如何执行I/O操作 构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...
- Clr Via C#读书笔记---计算限制的异步操作
线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...
随机推荐
- SSH2整合需要jar包解释
hibernate3.jar, Hibernate的库,必须使用的jar包 antlr-2.7.6.jar, 语法分析生成器 语言转换工具,hibernate利用它实现HQL到SQL的转换 cglib ...
- 阅读MySQL文档第20章:存储程序和函数
本文把阅读到的重点摘抄下来. 一.一个子程序要么是一个程序要么是一个函数.使用CALL语句来调用程序,程序只能用输出变量传回值.就像别其它函数调用一样,函数可以被从语句外调用(即通过引用函数名),函数 ...
- 调整home和根分区大小
目标:将VolGroup-lv_home缩小到100G,并将剩余的空间添加给VolGroup-lv_root ============================================= ...
- 16、SpringBoot-CRUD错误处理机制(3)
3).将自己指定的数据携带出去 出现错误以后,会来到/error请求,会被BasicErrorController 进行处理 响应出去的数据是由 getErrorAttributes 得到的( Abs ...
- HDU 1273 漫步森林(数学 找规律)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1273 漫步森林 Time Limit: 2000/1000 MS (Java/Others) M ...
- 大数据框架-spark
相关详细说明:https://www.csdn.net/article/2015-07-10/2825184 RDD:弹性分布式数据集. Operation:Transformation 和Actio ...
- 大数据框架-YARN
YARN(Yet Another Resource Negotiator): 是一种新的 Hadoop 资源管理器 [ResourceManager:纯粹的调度器,基于应用程序对资源的需求进行调度的, ...
- js取一个对象中的另一个对象
最开始的截图 原本是想取到其中的foodName 先是用一个for循环循环了下 for (var i=0;i<res.data.length;i++) { this.goodsList.res. ...
- 【2015 ICPC亚洲区域赛长春站 G】Dancing Stars on Me(几何+暴力)
Problem Description The sky was brushed clean by the wind and the stars were cold in a black sky. Wh ...
- 分享一个hybrid框架ionic
ionic 是一个 HTML5 应用程序开发框架. 可以使用 HTML.CSS 和 Javascript 构建接近原生体验的移动应用程序.具有速度快,界面现代化.美观等特点.下面一起看一下如何使用 安 ...