终于讲到泛型了。当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解。很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻。

泛型的概念:泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。

泛型的优势:源代码保护、类型安全、更加清晰的代码、更佳的性能。

原理:(关键字:开放类型,封闭类型)所有带泛型参数的类型都是一个开放式类型,它不能被实例化(类似接口),在具体使用时生成封闭类型(实际数据类型)。

泛型约束(至多一个主要约束,次要约束无限制):

泛型约束的使用:

        /// <summary>
/// 未加约束的T可以是任何类型,许多类型没有提供CompareTo方法,没有约束将导致代码不能编译,报"'T'不包含'CompareTo'的定义"错误
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o1"></param>
/// <param name="o2"></param>
/// <returns></returns>
private static T Min<T>(T o1,T o2) where T : IComparable<T>
{
if (o1.CompareTo(o2) < ) return o1;
return o2;
}

构造器约束:

//因为所有值类型都隐式有一个公共无参构造器。约束要求指定的任何引用类型也要有一个公共无参构造器
internal sealed class ConstructorConstraint<T> where T:new(){
public static T Factory(){
return new T();
}
}

由于泛型类型参数不能指定以下特殊引用类型:System.Object,System.Array,System.Delegate,System.MulticastDelegate,System.ValueType,System.Enum,System.Void,一些实参限制的实现可能要“特殊处理”,如以下使用静态构造器来保证类型是一个枚举类型。

internal sealed class GenericTypeThatRequiresAnEnum<T>{
static GenericTypeThatRequiresAnEnum(){
if(!typeof(T).IsEnum){
throw new ArgumentException("T must be an enumerated type");
}
}
}

泛型接口的优势:没有泛型接口,每次视图使用一个非泛型接口来操作一个值类型,都会发生装箱,而且会失去编译时的类型安全性。

委托和接口的逆变和协变泛型类型实参:

不变量:意味着泛型类型参数不能更改。(常用)

逆变量:意味着泛型类型参数可以从一个基类更改为该类的派生类。在C#中,用in关键字标记逆变量形式的泛型类型参数。逆变量泛型类型参数只出现在输入位置,比如作为方法的参数。

协变量:意味着泛型类型参数可以从一个派生类更改为它的基类。在C#中,是用out关键字标记协变量形式的泛型类型参数。协变量泛型类型参数只能出现在输出位置,比如作为方法的返回类型。

public delegate TResult Func<in T,out TResult>(T arg);

其它重要认知:

类型实参的指定和继承层次结构没有任何关系--理解这一点,有助于你判断转型的进行。
C#允许使用简化的语法来引用一个泛型封闭类型

using DateTimeList = System.Collections.Generic.List<System.DateTime>;

现在执行下面这行代码时,sameType会被初始化为true:

Boolean sameType = (typeof(List<DateTime>) == typeof(DateTimeList));

CLR支持泛型委托,目的是保证任何类型的对象都能以一种类型安全的方式传给一个回调方法。此外,泛型委托允许任何一个值类型实例在传给一个回调方法时不执行任何装箱处理。

一些验证问题:

1. 泛型类型变量的转型

将一个泛型类型的变量转型为另一个类型是非法的,除非将其转型为另一个约束兼容的类型

private static void CastingType<T>(T obj){
Int32 x = (Int32)obj;//错误
String s = (String)obj;//错误
string s2 = obj as String;//无错误
}

2. 设定默认值

private static void SettingDefaultValue<T>(){
T temp = default(T);
}

default关键字告诉C#编译器和CLR的JIT编译器,如果T是一个引用类型,就将temp设为null,如果T是一个值类型,就将temp的所有位设为0。

《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)的更多相关文章

  1. 《CLR.via.C#第三版》第二部分第13章节 接口 读书笔记(七)

    这章的书写感觉很普通,是些基础的认知知识. 其中一点的重要认知,泛型接口的好处(其实也是使用泛型的好处之一):编译时类型安全&处理值类型时减少装箱. 再说点书上没有的.本来这些知识我打算另外分 ...

  2. 精通正则表达式(第三版)——Mastering Regular Expressions,3rd Edition——读书笔记1

    基础知识介绍: 子表达式匹配 环视 引号内的字符串:"(^")*" 12小时制:(1[0123]|[1-9]):[0-5][0-9]*(am|pm) 24小时制:(([0 ...

  3. Java 线程第三版 第八章 Thread与Collection Class 读书笔记

        JDK1.2引入最有争议性的改变是将集合类默觉得不是Thread安全性的. 一.Collection Class的概述 1. 具有Threadsafe 的Collection Class: j ...

  4. 精通正则表达式(第三版)—Mastering Regular Expressions,3rd Edition—读书笔记2

    1.肯定断言:必须匹配一个字符 排除型字符组:匹配未列出字符的字符组 2.范围表示法——列出范围内所有的字符 大多数情况下,不会影响执行速度.但是,某些实现方式不能完全优化字符组.所以,最好是有范围表 ...

  5. 《CLR.via.C#第三版》第一部分读书笔记(一)

    最近开始仔细研读<CLR.via.C#第三版>这本书.读pdf文档确实很累.建议有条件的朋友还是买书看吧. 我的笔记用来记录我对这本书的理解,简化下逻辑,对每个部分我觉得是要点的进行归纳总 ...

  6. Python核心编程第三版第二章学习笔记

    第二章 网络编程 1.学习笔记 2.课后习题 答案是按照自己理解和查阅资料来的,不保证正确性.如由错误欢迎指出,谢谢 1. 套接字:A network socket is an endpoint of ...

  7. 《CLR.via.C#第三版》第二部分第4,5章节读书笔记(二)

    这两章全是理论性的东西,我觉得不必过于钻牛角尖.理论这东西,只有在长期的实践中去慢慢领悟才会深刻.下面我只写些我认为重要的关键知识. (一)类型转换 知识点:向基类型的转换被认为是一种安全的隐式转换: ...

  8. 《CLR.via.C#第三版》第二部分第8,9章节读书笔记(四)

    三种类型的构造方法: 实例构造器(引用类型):实例构造器永远不能被继承(所以方法前没有修饰符):如果类的修饰符为static(sealed和abstract),编译器根本不会在类的定义中生成一个默认构 ...

  9. 《CLR.via.C#第三版》第二部分第6,7章节读书笔记(三)

    第6章讲的是类型和成员基础 重要认知:虚方法 虚方法的设计原则:设计一个类型时,应尽量减少所定义的虚方法的数量. 首先,调用虚方法的速度比调用非虚方法慢. 其次,JIT编译器不能内嵌虚方法,这进一步影 ...

随机推荐

  1. 数据分析师的福音——VS 2017带来一体化的数据分析开发环境

    (此文章同时发表在本人微信公众号“dotNET开发经验谈”,欢迎右边二维码来关注.) 题记:在上个月的Connect() 2016大会上,微软宣布了VS 2017 RC的发布,其中为数据分析师带来了一 ...

  2. 一个简单的消息提示jquery插件

    最近在工作中写了一个jquery插件,效果如下: 就是一个简单的提示消息的一个东西,支持最大化.最小化.关闭.自定义速度.自定义点击事件,数据有ajax请求和本地数据两种形式.还有不完善的地方,只做了 ...

  3. Protocol Buffer搭建及示例

    本文来源:http://www.tanhao.me/code/150911.html/ Protocol Buffer(简称Protobuf或PB)是由Google推出的一种数据交换格式,与传统的XM ...

  4. Mac Android开发环境变量的配置(java、sdk、ndk、gradle)

    1.打开terminal 2.然后输入 vi .bash_profile 后按"e"进入编辑模式 3.输入想要配置的环境变量(Java.sdk.ndk.gradle): expor ...

  5. MIT 6.828 JOS学习笔记18. Lab 3.2 Part B: Page Faults, Breakpoints Exceptions, and System Calls

    现在你的操作系统内核已经具备一定的异常处理能力了,在这部分实验中,我们将会进一步完善它,使它能够处理不同类型的中断/异常. Handling Page Fault 缺页中断是一个非常重要的中断,因为我 ...

  6. wpf 触发器理解

    (1)属性触发器:其对应的类是Trigger.它在特定关联属性发生变化时被触发.一个属性的更改会在另一个属性中触发即时或动态更改. (2)数据触发器:其对应的类是DataTrigger.它在特定的CL ...

  7. Fancybox丰富的弹出层效果

    Fancybox是一款优秀的jquery插件,它能够展示丰富的弹出层效果.前面我们有文章介绍了facybox弹出层效果,相比facybox,fancybox显得功能更为齐全,它除了可以加载DIV,图片 ...

  8. Mac osx 安装PIL出现Some externally hosted files were ignored (use --allow-external PIL to allow).

    出现这个问题Some externally hosted files were ignored (use --allow-external PIL to allow)的主要原因是PIL的一些依赖库还没 ...

  9. 阅读jquery源码与js依赖加载的模块化!

    阅读源码肯定是先下载有注释的源码 我也是醉了,10309 行代码,在陆续续的一个月之内,看完了,虽有收获但收获不大, 直到又一次看jquery的github,怎么会有cmd????没听过使用jquer ...

  10. 使用 Graphviz 画拓扑图

    使用 Graphviz 画拓扑图 0)前述 本文着重讲一下 Graphviz 的风格控制,基础一些的就不在这里讲啦. graphviz 的主页是http://www.graphviz.org/. Gr ...