Chapter12 泛型

一提到泛型首先想到的应该是字符 <T> ,没错。。。它指的是一个未知的类型。

接下来会出现一些常用的术语,泛型类型、泛型方法、泛型接口、泛型委托、泛型的引用类型和值类型。。。。


泛型应该属于高级货,它支持另一种形式的代码的重用,即“算法重用”。

它的几个亮点:

  1. 源代码保护
  2. 类型安全的
  3. 更加清晰的代码
  4. 更佳的性能

举例最常用的List<T>,属于FCL中的泛型。。。

泛型基础结构

1.开放类型和封闭类型

开放类型:具有泛型类型参数的类型,CLR禁止构造开放类型的任何实例

eg:Dictionary<,>是一个开放类型,它有2个类型参数,但无法创建该类型的一个实例

封闭类型:所有类型实参传递的都是实际数据类型,CLR允许构造其实例

eg:Dictionary<String,object>是个封闭类型。

这里还有一个特别需要注意的地方:

每个封闭类型都有自己的静态字段,假如List<T>定义了任何静态字段,这些字段不会在List<DateTime>和一个List<String>之间共享,每个封闭类型对象都有其自己的静态字段。。。

另外,假如一个泛型类型定义了一个静态构造器,那么针对每个封闭类型,这个构造器都会执行一次。。在泛型类型上定义一个静态构造器的目的就是保证传递的类型实参满足特定的条件。。。

例如 T必须满足是枚举类型,可能你会想到约束来指定那些实参是有效的,尼玛使用约束却无法将类型实参限制为“仅枚举类型”,所以还是有静态构造器来保证T是个枚举类型

上面加粗的是比较坑爹的知识点,容易遗忘。。。

2.泛型类型和继承

泛型类型也能派生。。。。

例如 List<T>继承自Object,那么List<String> List<Guid>也是派生自Object。。。。

例如 DictionaryStringKey<TValue>派生自Dictionary<String,TValue>,那么DictionaryStringKey<Guid>也派生自Dictionary<String,Guid>。。。

3.泛型类型的同一性

可能<T>式的写法有损类型的可读性,尼玛有些人会从一个复杂难写的泛型类型派生一个新类型,并指定了所有实参。。。

坑爹的是这个新的类型与复杂难写的泛型类型属于两个不同类型对象,没啥可比性。。。所以这样写会有损泛型类型的同一性。。。

不过C#也提供了一种方式利用using指令

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

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

这样类型的同一性和相等性得到类维持。。。

4.代码爆炸

很显然,既然使用了泛型,CLR要为每种不同的方法/类型组合生成本地代码,成为代码爆炸。。。。

当然MS会为其做一些优化来缓解。

  1. 假定一个特定的类型实参调用了一个方法,以后在次使用相同的类型实参来调用这个方法,CLR只会为这个方法/类型组合编译一次代码。。。
  2. 第二种是CLR认为所有引用类型实参都是完全相同的,所有代码都能共享
  3. 对于值类型,CLR就必须专门为那个值类型生成本地代码。。。

泛型接口

在没有泛型接口时,每次在试图使用一个非泛型接口来操纵一个值类型,都会反生装箱,而且会失去编译时的类型安全。。。。。

泛型委托

目的是保证任何类型对象都能以一种类型安全的方式传给一个回调方法。。

FCL中有很多预定义的泛型Action和Func委托

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

  • 不变量 意味着泛型类型参数不能改变。
  • 逆变量 意味着泛型类型参数可以从一个基类型更改为该类的派生类型,在C#中,用in关键字标记,而且只出现在输入位置。
  • 协变量 意味着泛型类型参数可以从一个派生类型更改为它的基类型,在C#中,用out关键字标记,只出现在输出位置。

泛型方法

其他。。。。。。。。。。

 

 

 

 

 

posted @ 2013-02-20 16:19  hailiang2013  阅读(156)  评论(0)    收藏  举报