07c#协变逆变
namespace 协变逆变
{
class Program
{
static void Main(string[] args)
{
//问题1:为什么会有协变逆变?
//首先,由里氏替换我们知道,子类可以安全的赋值给父类。
//(不熟悉可以会议六大设计原则//solid:
//s——单一职责
//o——开闭原则
//l——里氏替换
//I——接口隔离
//d——迪米特法则,依赖倒置原则)
Animal animal = new Cat();//合法
//其次,一定要知道, 协变逆变只是针对与泛型接口与泛型委托而言的。
//生命两组正常的委托
MyDelegate<Animal> myDelegate1 = new MyDelegate<Animal>((p) => { p.Eat(); return new Animal(); });//合法
MyDelegate<Cat> myDelegate2 = new MyDelegate<Cat>((p) => { p.Miao(); return new Cat(); });//合法
MyDelegate<Animal> myDelegate3 = new MyDelegate<Cat>((p) => { p.Miao(); return new Cat(); });//非法。
//试想一下:如果合法了,那么 myDelegate3(new Animal()),参数对象animal,根本没有Miao()方法,编译器会出错的。
MyDelegate<Cat> myDelegate4 = new MyDelegate<Animal>(() => { return new Animal(); });//非法。
//同样试想一下:如果合法了,那么返回一个Animal类型,实际需要的是Cat类型,上层调用Miao()方法,编译器仍会出错的。
//本质原因是,虽然Animal与Cat有继承关系,但是, MyDelegate<Animal>与 MyDelegate<Cat>并无继承关系。
//我们希望是合法的,并且实际中也符合逻辑。所以框架开发者为这一目的,提出了协变的概念。如下
MyDelegateOut<Animal> myDelegate5 = new MyDelegateOut<Cat>(() => { return new Cat(); });//合法
//返回子类类型赋值给父类类型合法。这其实就是支持协变,通过out参数
MyDelegateOut<Cat> myDelegate6 = new MyDelegateOut<Animal>(() => { return new Animal(); });//非法。
//返回父类类型赋值给子类类型不合法
MyDelegateIn<Cat> myDelegateIn7 = new MyDelegateIn<Animal>((p) => { p.Eat(); });
//需要传递父类的地方给一个子类,完全合法,这就是支持逆变。
MyDelegateIn<Animal> myDelegateIn8 = new MyDelegateIn<Cat>((p) => { p.Miao(); });
//需要传递子类的地方给一个父类,不合法,父类根本没有miao() 方法提供。
}
}
class Animal
{
public void Eat()
{
Console.WriteLine("吃");
}
}
class Cat : Animal
{
public void Miao()
{
Console.WriteLine("喵");
}
}
delegate T MyDelegate<T>(T t);//普通委托
delegate void MyDelegateIn<in T>(T t);//支持逆变
delegate T MyDelegateOut<out T>();//支持协变
}