协变和逆变out in 委托 ------------知识点5

什么是协变 out 和逆变 in

首先将out in与 ref out这两个区分开来,ref out 是关于参数的引用传递的,
协变:out
和谐的变化,自然的变化
因为 里氏替换原则 父类可以装子类
所以 子类变父类
比如 string 变成 object
感受是和谐的

逆变:in

逆常规的变化,不正常的变化
因为 里氏替换原则 父类可以装子类 但是子类不能装父类(但是为什么子类确实在逆变里装了父类)
所以 父类变子类
比如 object 变成 string
感受是不和谐的
// 逆变其实也是从子类转成父类的,因为它其实是参数输出,子类容器放入的虽然是父类,但是调用时候的方法还是父类的,传入的参数是子类的,所以还是子类对象转化为父类
也可以简单理解为,in代表进局子了,不和谐,叛逆的,out代表出局子了,很和谐

知识点1

//1.返回值 和 参数
//用out修饰的泛型 只能作为返回值 协变
delegate T TestOut< out T>();
//用in修饰的泛型 只能作为参数,逆变
delegate void TestIn< in T>(T t);

using System;

namespace Lesson17_协变逆变
{

    //协变和逆变是用来修饰泛型的
    //协变:out 
    //逆变:in
    //用于在泛型中 修饰 泛型字母的 
    //只有泛型接口和泛型委托能使用
    #endregion

    #region 知识点二 作用
    //1.返回值 和 参数
    //用out修饰的泛型 只能作为返回值,T不能当做参数传递 协变
    delegate T TestOut<out T>();
    //用in修饰的泛型 只能作为参数 ,T不能当做返回类型 逆变
    delegate void TestIn<in T>(T t);

    //2.结合里氏替换原则理解
    class Father
    {

    }

    class Son:Father
    {

    }
    #endregion
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("协变逆变");
            #region 知识点二 作用(结合里氏替换原则理解)
            //协变 父类总是能被子类替换
            // 看起来 就是 son ——> father
            //这里是一个协变,所以不能有参数传递,只能返回Son对象
            TestOut<Son> os = () =>
            {
                return new Son();
            };
			//上面返回的Son对象被父级Father的委托装起来了,这里可以理解为父类容器装的子类对象,注意如果
			  //  delegate T TestOut<out T>(); 这里不加out ,那么下面这样写也会报错,加了out系统才会自动给你转换成父级
            TestOut<Father> of = os;
            Father f = of();//实际上 返回的 是os里面装的函数 返回的是Son

            //逆变 父类总是能被子类替换
            //看起来像是 father——>son 明明是传父类 但是你传子类 不和谐的
             //这里是一个逆变,所以不能有返回值,传入的value也是Father类型的
             //
            TestIn<Father> iF = (value) =>
            {

            };
			//这里iF其实就是父类委托,存入到了子类委托中,为什么能存进去,这不是违反了里式转换?看下面
            TestIn<Son> iS = iF;
			//这里只是存进去,并没有进行实质的子类转成父类,在去调用iS方法的时候,其实本质还是调用的iF,调用iS传入的参数必须是new Son(),其实就是 iF(new Son()),等于还是将Son转化为了Father,其实最后还是遵循了里式转换原则!!!
		//	逆变其实也是从子类转成父类的,因为它其实是参数输出,子类容器放入的虽然是父类,但是调用时候的方法还是父类的,传入的参数是子类的,所以还是子类对象转化为父类
            iS(new Son());//实际上 调用的是 iF ,delegate void TestIn< in T>(T t);所以必须要传入(new Son()
            #endregion
        }
    }

    //总结
    //协变 out
    //逆变 in
    //用来修饰 泛型替代符的  只能修饰接口和委托中的泛型

    //作用两点
    //1.out修饰的泛型类型 只能作为返回值类型 in修饰的泛型类型 只能作为 参数类型
    //2.遵循里氏替换原则的  用out和in修饰的 泛型委托 可以相互装载(有父子关系的泛型)
    //  协变  父类泛型委托装子类泛型委托    逆变 子类泛型委托装父类泛型委托
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值