C#中的协变和逆变

简介: C#中的协变和逆变

前言


这篇文章简单说说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();


协变和逆变


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


具体如下代码所示:

   delegate T AgeDelegate<T>();         
        static AhuiPeople GetAge()
        {
            return new AhuiPeople();
        }


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

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

错误提示


这就是上面解释的那样子,基类和派生类之间可以进行转换但是委托之间未存在关联,无法进行强制类型的转换。


那么想解决这个问题就引入了协变来解决。


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


 delegate T AgeDelegate<out T>();     


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


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


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


这种在期望传入基类时允许传入派生对象的特性叫做逆变。 逆变使用关键字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();

输出结果


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


目录
相关文章
|
6月前
|
安全 C#
C#进阶-协变与逆变
我们知道子类转换到父类,在C#中是能够隐式转换的。这种子类到父类的转换就是协变。而另外一种类似于父类转向子类的变换,可以简单的理解为逆变。逆变协变可以用于泛型委托和泛型接口,本篇文章我们将讲解C#里逆变和协变的使用。逆变和协变的语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。
62 0
|
C# 开发者
C#——协变逆变
C#——协变逆变
95 0
|
算法
一起谈.NET技术,C#4.0新特性-&quot;协变&quot;与&quot;逆变&quot;以及背后的编程思想
  在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相信有很多人不能很清晰地说出他们之间的区别。
904 0
|
算法
C#4.0新特性-&quot;协变&quot;“.NET研究”与&quot;逆变&quot;以及背后的编程思想
  在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相信有很多人不能很清晰地说出他们之间的区别。
1094 0
|
C# 编译器 Java
C# 逆变与协变
原文:C# 逆变与协变 该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章《委托与匿名委托》、《匿名委托与Lambda表达式》以便帮你建立完整的知识体系。
1347 0