写在前面:
简单说一下看书的感受,这一章看了五六遍,一个星期,反反复复看,工作休息没事的时候看看,玩手机累的时候看看,躺着看电视的时候看看,终于梳理通了
看书的感受是:
1.书中有些话太过于精简(且代码不够严谨、不够详细),导致看不懂
例如:泛型类继承泛型类的要求,书中写着是“必须重复接口的泛型类型,或者必须指定基类的类型”
不懂,我就试验,成功后自己总结的话是前半句意思是:子类泛型<>中间标识和泛型基类或者实现的泛型接口<>中间的标记一样,例如泛型基类是,泛型子类继承则是 子类:父类—就是要是T,都是T
后半句意思是:子类继承的时候可以直接指定父类泛型的类型,例如子类:父类
2.有些知识不在这个章节或者这个章节以前出现
3.示例代码有些太过复杂,不利于对单纯的知识讲解
4. 章节里知识点的安排顺序很好,就像这章,先说泛型的特性,在说泛型用到类、接口、结构、方法的过程
泛型的特征……
泛型概述:CLR的特性,出现在.NET2.0,未出现前用object实现“泛型效果”
性能好
1.没有拆装箱
为什么没有拆装箱,我不清楚,说是JIT动态生成,但我知道什么是拆装箱,而且这样的做法会时性能损失(前面博文我也解释了为什么会性能损失),但是我们可以用简单的代码来测试:
你用ArrayList来Add不同类型的数据,然后将其中的某个数据赋值给int类型,需要强转才成功
你用匿名类型var的ListAdd数据,然后将其中的某个数据赋值给int类型,不需要强转成功- 解释这么多呢,是因为我感受深刻:
1.我现在的BOSS很早之前就说放弃使用ArrayList这种数据结构,现在明白为什么了
2.前段时间我去面试,问我List的效率怎么样,我回答不出来,他说没有拆装箱,很快的,现在我才清楚了
2.内存占用
- 在IL中只有一份代码
- 例如我List这个类,我实例化的时候List和List两种类型各实例化一次,代码在IL中只有一份
- 在内存中情况
- 如果你泛型是值类型,那老规矩,还是栈上开辟值类型控件的大小存储
- 如果你是引用类型,那老规矩,还是在堆上,存引用
- 在IL中只有一份代码
类型安全
- 就如上面的解释中的测试来说,你List已经明确了类型了,没法Add string类型的数据,在入口的时候就不让你添加其他类型数据,达到了类型安全
复用
- 代码复用
这个很容易理解,你的泛型方法想针对于int来一套,针对string来一套,你可以用object,可以用泛型,如果没有这两个,你只能写两遍同样的代码,只是参数类型不同而已
- 代码复用
泛型的语法……
1.命名
- 用 T命名,当然了,你也可以用D,如果这个泛型是和其他的东东有关,例如我这个泛型是用来输入的,我可以叫TInput,如果我这个泛型类继承了另一个泛型类File,我可以叫TFile
2.默认值
- 语法T t = default(T); 将t赋值为null
3.值类型赋空
- 使用?,例如 int ? i = null;或者 bool ? j = null;
4.语法(我不知道该叫啥)
-
- 使用??,例如 string i = null ?? “str”; ??左边是null的话就为右边,所以i是“str”
-
5.约束
- 这个意思有些绕口
- 我举例来说:
- A类实现B接口
- 泛型类C实现B接口
- 泛型类C中可以处理A类对象
- 语法 用where
- 例如class Test 左尖括号 T 右尖括号 where T : B接口
- 约束还可以用于结构,有兴趣自己查
泛型应用在各种结构中
- 泛型+类
- 1.泛型类能继承泛型类(泛型接口)。条件:
-重复 “基” 的泛型类型(书中是重复基类的泛型类型,我还没有接受将继承的接口也称作基类)
- 意思是说,我基的泛型类型尖括号中的字母,是T,那我子类的泛型尖括号也写T
-指定 “基” 的泛型类型
- 意思是说,继承的时候直接指定基的泛型具体类型,<int>、<string>……明确指定
- 2.静态成员
- 泛型类中的每一个静态成员在每种类型的实例化都各有也仅有一个
- 泛型 + 接口
- 1.协变
- 关键字:out
- 使用:例如interface ITe 左键括号out t 右键括号 (csdn博客中用尖括号中间的字不显示)
- 效果:定义的函数中泛型类型T只能用作是返回值
- 2.逆变(抗变)
- 关键字:in
- 使用:上面out换成in
- 效果:定义的函数中泛型类型T只能用作为参数(不影响有其他类型的参数)
- 泛型 + 方法
- 不管是泛型的类、泛型的接口、泛型的结构,还是非泛型的类,非泛型的接口、非泛型的结构,都可以定义泛型的方法