07c#协变逆变

发布时间 2024-01-07 14:22:55作者: 猿锋博客

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>();//支持协变

}