泛型之逆变和协变总结

泛型之逆变和协变总结

c#

泛型

逆变

协变

  • 变的概念
  • 协变(Foo<父类> = Foo<子类> )
  • 逆变(Foo<子类> = Foo<父类>)
  • 逆变与协变的相互作用

变的概念

  1. //父类 = 子类


  2. string str = "string"; 

  3. object obj = str;//变了 

协变(Foo<父类> = Foo<子类> )

  1. //泛型委托:


  2. public delegate T MyFuncA<T>();//不支持逆变与协变 

  3. public delegate T MyFuncB<out T>();//支持协变 


  4. MyFuncA<object> funcAObject = null; 

  5. MyFuncA<string> funcAString = null; 

  6. MyFuncB<object> funcBObject = null; 

  7. MyFuncB<string> funcBString = null; 


  8. funcAObject = funcAString;//编译失败,MyFuncA不支持逆变与协变 

  9. funcBObject = funcBString;//变了,协变 

逆变(Foo<子类> = Foo<父类>)

  1. public delegate void MyActionA<T>(T param);//不支持逆变与协变


  2. public delegate void MyActionB<in T>(T param);//支持逆变 


  3. MyActionA<object> actionAObject = null; 

  4. MyActionA<string> actionAString = null; 

  5. MyActionB<object> actionBObject = null; 

  6. MyActionB<string> actionBString = null; 


  7. actionAString = actionAObject;//MyActionA不支持逆变与协变,编译失败 

  8. actionBString = actionBObject;//变了,逆变 


在泛型参数上添加了in关键字作为泛型修饰符的话,那么那个泛型参数就只能用作方法的输入参数,或者只写属性的参数,不能作为方法返回值等,总之就是只能是“入”,不能出。out关键字反之。

逆变与协变的相互作用

  1. public interface IBar<in T> { }


  2. //应该是in 

  3. public interface IFoo<in T> 



  4. void Test(IBar<T> bar); 



  5. //还是out 

  6. public interface IFoo<out T> 



  7. void Test(IBar<T> bar); 



有协变能力的IFoo要求它的泛型参数(IBar)有逆变能力

时间: 2024-08-26 06:29:05

泛型之逆变和协变总结的相关文章

ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof

一:如何去学习?都去学习什么? 1:学习优秀项目的设计思想,多问几个为什么,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中 2:学习优秀项目的代码风格,代码的封装设计思想,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中,每行代码都要用心去写,每一行代码都要力求使最简洁的 3:学习别人遇到问题是如何分析问题,解决问题的方法是什么 4:遇到新东西应该如何去学习:1:先研究要学习的东西作用是什么 ,有什么好处  2:如何使用:具体的语

C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)

一.为什么使用泛型? 泛型其实就是一个不确定的类型,可以用在类和方法上,泛型在声明期间没有明确的定义类型,编译完成之后会生成一个占位符,只有在调用者调用时,传入指定的类型,才会用确切的类型将占位符替换掉. 首先我们要明白,泛型是泛型,集合是集合,泛型集合就是带泛型的集合.下面我们来模仿这List集合看一下下面这个例子: 我们的目的是要写一个可以存放任何动物的集合,首先抽象出一个动物类: //动物类 public class Animal { //随便定义出一个属性和方法 public Strin

逆变与协变详解

逆变(contravariant)与协变(covariant)是C#4新增的概念,许多书籍和博客都有讲解,我觉得都没有把它们讲清楚,搞明白了它们,可以更准确地去定义泛型委托和接口,这里我尝试画图详细解析逆变与协变. 变的概念 我们都知道.Net里或者说在OO的世界里,可以安全地把子类的引用赋给父类引用,例如: 1 2 3 //父类 = 子类 string str = "string"; object obj = str;//变了 而C#里又有泛型的概念,泛型是对类型系统的进一步抽象,比

EF中逆变和协变

EF中的增删改查: 实现步骤: 1.声明一个EF的上下文. bjhksjEntities dbContext = new bjhksjEntities(); 2.声明一个实体. HKSJ_USERS user = new HKSJ_USERS(); user.LoginName = "ssss"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss";

C# 逆变与协变

原文:C# 逆变与协变 该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章<委托与匿名委托>.<匿名委托与Lambda表达式>以便帮你建立完整的知识体系. 在C#从诞生到发展壮大的过程中,新知识点不断引入.逆变与协变并不是C#独创的,属于后续引入.在Java中同样存在逆变与协变,后续我还会写一篇Java逆变协变的文章,有兴趣的朋友可以关注一下. 逆变与协变,听起来很抽象.高深,其实很简单.看下面的代码: class Person {

Java 逆变与协变

最近一直忙于学习模电.数电,搞得头晕脑胀,难得今天晚上挤出一些时间来分析一下Java中的逆变.协变.Java早于C#引入逆变.协变,两者在与C#稍有不同,Java中的逆变.协变引入早于C#,故在形式没有C#直观(Google推出的基于jvm的Kotlin语音,则完全走向了C#的路线).Java中逆变.协变,在泛型集合使用中更多些.更直观(像C#中的用法在Java中较少出现,但并非不可). 正常泛型集合的使用 示例代码如下: public static void main(String[] arg

Java中的逆变与协变(转)

看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); //type mismatch List<? extends Number> list = new ArrayList<Number>(); list.add(new Integer(1)); //error list.add(new Float(1.2f)); //error 有人会

Java中的逆变与协变

看下面一段代码 Number num = new Integer(1); ArrayList<Number> list = new ArrayList<Integer>(); //type mismatch List<? extends Number> list = new ArrayList<Number>(); list.add(new Integer(1)); //error list.add(new Float(1.2f)); //error 有人会

OOP中的逆变和协变

逆变和协变在存在于强类型语言中,尽管非常少提及,可是里面蕴含了面向对象的世界观.感谢和我一起讨论这个问题的人. 这里用了C#.Scala的语法作为演示样例,事实上逆变和协变的概念跟语言本身关系不大,事实也是如此. 一.定义 逆变的參数能够由指定的类型的子类型取代,协变的參数能够由指定类型的父类型取代. Scala中的逆变声明:Function[-A,+B] ;当中泛型-A为逆变类型.在实例化时,能够使用A类型或者A类的子类型. 二.协变与逆变的用途不同 1.语义 Scala中,函数的原型之中的一