[From 12] 泛型(因为泛型用的比较多,我就只记录了一下我平时不太熟悉或者用的少的)
一.泛型中的开放类型和封闭类型
1.开放类型:
定义:具有泛型类型参数的类型称为开放类型。
特点:CLR禁止构造开放类型的任何实例。(这类似于CLR禁止构造接口类型的实例。)
2.封闭类型:
定义:所有类型参数都传递了实际的数据类型,类型就称为封闭类型。
特点:CLR可以构建实例
二.泛型接口
注:没有泛型接口,每次用非泛型接口(如IComparable)来操纵值类型都会发生装箱,而且会失去编译时的类型安全性。
三.委托和接口的逆变和协变泛型类型实参
1.不变量(invariant):意味着泛型类型参数不能改变。
2.逆变量(contravariant):意味着泛型类型参数可以从一个类更改为它的某个派生类。在C#使用in关键字标记逆变量形式的泛类型参数。逆变量泛型类型参数只出现在输出位置,比如作为方法的参数。
3.协变量(covariant):意味着泛型类型参数可以从一个类改为它的某个基类。C#是用out关键字标记协变量形式的泛型类型参数。协变量泛型类型参数只能出现在输出位置,比如作为方法的返回类型。
建议:使用要获取泛型参数和返回值的委托时,建议尽量为逆变性和协变性指定in和out关键字。这样做不会有不良反应,并使你的委托能在更多的情形中使用。
四.泛型约束
1.主要约束:
例如:
public class XXX<T> : where T : Stream
这种情况T只能是Stream或者Stream的派生类
注意:不能只能以下特殊引用类型,如图
2.次要约束:
1.接口约束:如果继承了接口,则需要实现所继承接口的方法
2.类型参数约束(裸类型参数):方法类型的约束(我的理解),跟主类型有点像,但是可以用另一个泛型去约束这个泛型。
例如:
3.构造器约束:
例如:
上图表示,该泛型一定要具有一个公共无参的构造器。
注意:如果同时使用构造器约束和struct约束,C#编译器会认为这是一个错误,是多余的。
五.泛型需要注意的地方:
1.泛型转为其他类型是非法的,除非转型为与约束兼容的类型。
2.泛型设为null是非法的,除非将泛型类型约束成引用类型。
3.无论泛型是否被约束,与null做比较都是合法的。(除非T被约束为struct,因为值类型不能与null作比较
4.如果泛型类型不能肯定是引用类型,对同一个泛型类型的两个变量进行比较是非法的
5.泛型作为操作数(+,-,*,/ 等)使用会出现大量问题。具体看本书256~257