应用在泛型委托,泛型接口上。
一。准备知识——赋值兼容性
将派生类的对象赋值给基类型变量。
class Animal { public int NumerOfLegs = 4; } class Dog:Animal { }
class Program { static void Main(string[] args) { Animal a1 = new Animal(); Animal a2 = new Dog(); // 派生类变量赋给基类型变量————继承了基类的字段 Console.WriteLine($"Number of dog legs:{a2.NumerOfLegs}"); } }
二。协变
将委托参数类型的派生类型赋值给委托参数类型的基类型,以下代码编译报错——无法隐式类型转换
出错原因:泛型委托参数类型虽然存在派生关系,但委托Factory<Dog>与Factory<Animal>间不存在派生关系,所在赋值兼容性不适用。
class Animal { public int Legs = 4; } class Dog : Animal { } delegate T Factory<T>(); // 有返回值,无参数泛型委托 class Program { // 匹配Factory委托的方法 static Dog MakeDog() { return new Dog(); } static void Main(string[] args) { Factory<Dog> dogMaker = MakeDog; // 使用静态方法给委托赋值 Factory<Animal> animalMaker = dogMaker; // 编译报错:无法隐式类型转换 Console.WriteLine(animalMaker().Legs.ToString()); } }
==》》正式引入协变
将派生类型用作输出值,可以赋给基类型引用。为了让编译器知道我们的期望,必须使用out标记委托声明中的类型参数
用下面代码替换上面委托定义行。
delegate T Factory<out T>();
三。逆变
只作输入参数类型为基类型,可以传入派生类对象
class Animal { public int NumberOfLegs = 4; } class Dog : Animal { } delegate void Action1<in T>(T a); // 无返回值,有参数泛型委托 class Program { // 匹配Factory委托的方法 static void ActOnAnimal(Animal a) { Console.WriteLine(a.NumberOfLegs); } static void Main(string[] args) { Action1<Animal> act1 = ActOnAnimal; // 使用静态方法给委托赋值 Action1<Dog> dog1 = act1; // 基类参数委托赋给派生类参数委托 dog1(new Dog()); // 传入派生类对象 } }
四。协变与逆变不同
五。接口的协变与逆变
六。关于可变的更多内容
七。不变
标签:委托,Factory,Dog,contravariance,Animal,协变,可变性,class From: https://www.cnblogs.com/duju/p/16965582.html