C#泛型——约束|协变|逆变
1、泛型使用
在生命时可以使用<>,可以写一个标识符代替一些数据类型,在声明时给出明确定义。
非常强大,因此需要约束。
2、泛型约束
where T: struct//值类型约束,要求泛型必须为基本数据类型
where T: class //引用类型约束,要求泛型必须为类类型
where T: new()//默认构造方法约束,要求泛型必须有默认构造方法(抽象类abstract、接口interface、密封类sealed等都不可以)
多重约束之间用逗号隔开
3、泛型&协变与逆变
(1)协变(子转父)与逆变(父转子)
泛型是一种不指定的数据类型,不同的泛型之间没有继承关系。
但通过泛型定义的类在使用时需要指定泛型的具体类型,这些具体类型之间有时会具备父子关系。
通常情况下,同一个使用泛型的类在不同具体的实例化的同时,对象引用之间不允许相互赋值。
也就是说,A和A之间没有父子关系,默认为不变关系(没有关系)。
这个时候逆变、协变、和不变关系只能自己声明。
(2)使用泛型时协变与逆变的声明out/in
delegate T d1<out T> ();//协变声明
delegate void d2<in T> (T t);//逆变声明
声明协变泛型后, 使用子类的委托对象 可以向 使用父类泛型的委托引用 赋值:
d1<Dog> d11 = MakeAnimal;
d1<Animal> d12 = d11;
声明逆变泛型后, 使用父类的委托对象 可以向 使用子类泛型的委托引用 赋值:
d2<Animal> d21 = MakeAnimal2;
d2<Dog> d22 = d21;
协变泛型只能做返回值,逆变泛型只能做参数。
(3)适用范围
泛型接口和泛型委托。
个人感觉是因为泛型接口和泛型委托只能出现在赋值表达式的左侧,作为被赋值的一方,
泛型类有可能不需要声明引用,泛型方法不可能作为对象引用出现在赋值表达式的左侧。