C#中的协变和逆变

ca7f9b21b454525738990a04058e52d0.png

前言

这篇文章简单说说C#中的协变和逆变。

在C#编程中,由于存在类型之间的强制转换,很容易会出现所谓的类型可变性说法,存在协变、逆变、不变三种。

就比如前一篇文章介绍的泛型概念,如果创建了泛型类型的实例,编译器会接受泛型类型声明以及类型参数来创建构造类型。但是在日常使用过程中,我们可能会将派生类型分配给基类型的变量,有时候会出现错误。

这里就存在一个赋值兼容性问题。

每一个变量都有一种类型,可以将派生类对象的实例赋值给基类变量(好比之前子类声明的变量可以赋值给父类声明的变量一样)。

如下所示:

class People
        {
            public int Age = 27;
        }

        class AhuiPeople : People
        {

        }
People ahui = new People();
            People people = new AhuiPeople();

            Console.WriteLine("Age:"+people.Age);
            Console.ReadKey();
7171a848397b13bee688850fc1045cab.png

协变和逆变

我们按照同样的逻辑,在泛型委托中进行这种强类型的转换,会发现即使基类和派生类之间可以进行正常的转换,但是委托之间不能进行转换会出现异常错误提示。

具体如下代码所示:

delegate T AgeDelegate<T>();         

        static AhuiPeople GetAge()
        {
            return new AhuiPeople();
        }

在转换过程中,委托的具体用法,但是这样子编译器提示错误。

AgeDelegate<AhuiPeople> ahui = GetAge;
            AgeDelegate<People> people = ahui;

错误提示409daaeefe58867b6ce63647d0ef289e.png

这就是上面解释的那样子,基类和派生类之间可以进行转换但是委托之间未存在关联,无法进行强制类型的转换。那么想解决这个问题就引入了协变来解决。

如果派生类只是用于输出值,那么这种结构化的委托有效性之间的常数关系叫做协变,可通过主动告知编译器我们的期望,使用Out关键字标记委托声明中的类型参数。

delegate T AgeDelegate<out T>();

修改成这样子后,上面错误演示的代码编译器就可以正常编译通过了。

b78d5f00ab9a5d40e98257e4ab165e1c.png上面简单介绍了协变,那么接下来我们来看逆变是什么。

其实逆变就是在委托中既要声明委托类型,也要在委托方法中有实参。

这种在期望传入基类时允许传入派生对象的特性叫做逆变。逆变使用关键字in来标记。

具体如下代码所示:

delegate void AgeDelegate<in T>(T p); 

        static void GetAge(People p)
        {
            Console.WriteLine(p.Age);
        }
AgeDelegate<People> ahui = GetAge;
            AgeDelegate<AhuiPeople> people = ahui;

            people(new AhuiPeople());
            Console.WriteLine();
            Console.ReadKey();

输出结果1a62f6d656f89071e4062f3d4901db18.png

既然协变和逆变可以使用在委托上,那么接口上也可以使用,此时也需要使用out和in关键字。

寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看得见的。

原创不易,给个关注。

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值