using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace MyGeneric.CC
{
/// <summary>
/// 逆变(contravariant)与协变(covariant):只能用在接口和委托上面
/// out “协变”->”和谐的变”->”很自然的变化”->string->object :协变。 负责修饰返回值
/// in “逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。 负责修饰参数
/// </summary>
public class CCTest
{
public static void Show()
{
Child child = new Child();
Parent parent = new Parent();
Parent parent77 = new Child();
Parent parent88 = (Parent)child;
{
List<Parent> parentList = new List<Parent>();
//List<Parent> parentList3 = new List<Child>();//需要转换才行 List<Parent> parentList1 = new List<Child>().Select(c => (Parent)c).ToList();//需要自己转换 IEnumerable<Parent> parentList2 = new List<Child>();//协变 只能是返回值,返回的Child必然是Parent的 Action<Child> act = new Action<Child>(c => { });//按说都是child才行 Action<Child> act1 = new Action<Parent>(c => { });//l使用act1的时候,参数只能是Child,必然满足lambda表达式对parent的类型要求 act(child);
act1(child);
}
{
//增强了接口、委托的适用范围,同时保证了类型安全
IMyList<Child, Parent> list1 = new MyList<Child, Parent>();
{
list1.Show(child);
Parent parent1 = list1.Get();
Parent parent2 = list1.Do(child);
}
IMyList<Child, Parent> list2 = new MyList<Child, Child>();
{
list2.Show(child);
Parent parent1 = list2.Get();
Parent parent2 = list2.Do(child);
}
IMyList<Child, Parent> list4 = new MyList<Parent, Parent>();
{
list4.Show(child);
Parent parent1 = list4.Get();
Parent parent2 = list4.Do(child);
}
IMyList<Child, Parent> list3 = new MyList<Parent, Child>();
{
list3.Show(child);
Parent parent1 = list3.Get();
Parent parent2 = list3.Do(child);
}
}
} }
public class Parent
{
} public class Child : Parent
{
} public interface IMyList<in inT, out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t); ////out 只能是返回值 in只能是参数
//void Show1(outT t);
//inT Get1(); } public class MyList<T1, T2> : IMyList<T1, T2>
{ public void Show(T1 t)
{
Console.WriteLine(t.GetType().Name);
} public T2 Get()
{
Console.WriteLine(typeof(T2).Name);
return default(T2);
} public T2 Do(T1 t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T2).Name);
return default(T2);
}
}
}

逆变(contravariant)与协变(covariant):只能用在接口和委托上面的更多相关文章

  1. 协变(covariant)和逆变(contravariant)

    我们知道子类转换到父类,在C#中是能够隐式转换的.这种子类到父类的转换就是协变. 而另外一种类似于父类转向子类的变换,可以简单的理解为“逆变”. 上面对逆变的简单理解有些牵强,因为协变和逆变只能针对接 ...

  2. 不变(Invariant), 协变(Covarinat), 逆变(Contravariant) : 一个程序猿进化的故事

    阿袁工作的第1天: 不变(Invariant), 协变(Covarinat), 逆变(Contravariant)的初次约 阿袁,早!开始工作吧. 阿袁在笔记上写下今天工作清单: 实现一个scala类 ...

  3. C#4.0新特性(3):变性 Variance(逆变与协变)

    一句话总结:协变让一个粗粒度接口(或委托)可以接收一个更加具体的接口(或委托)作为参数(或返回值):逆变让一个接口(或委托)的参数类型(或返回值)类型更加具体化,也就是参数类型更强,更明确. 通常,协 ...

  4. Java逆变(Covariant)和协变(Contravariant)

    1. 定义 逆变和协变描述的经过类型变换后的类型之间的关系.假如A和B表示类型,f表示类型变换,A ≤B表示A是B的子类型,那么 如果A ≤B,f(A) ≤f(B),那么f是协变 如果A ≤B,f(B ...

  5. 【温故而知新-万花筒】C# 异步编程 逆变 协变 委托 事件 事件参数 迭代 线程、多线程、线程池、后台线程

    额基本脱离了2.0 3.5的时代了.在.net 4.0+ 时代.一切都是辣么简单! 参考文档: http://www.cnblogs.com/linzheng/archive/2012/04/11/2 ...

  6. Scala中的协变,逆变,上界,下界等

    Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...

  7. 协变(covariance),逆变(contravariance)与不变(invariance)

    协变,逆变与不变 能在使用父类型的场景中改用子类型的被称为协变. 能在使用子类型的场景中改用父类型的被称为逆变. 不能做到以上两点的被称为不变. 以上的场景通常包括数组,继承和泛型. 协变逆变与泛型( ...

  8. Scala 基础(十六):泛型、类型约束-上界(Upper Bounds)/下界(lower bounds)、视图界定(View bounds)、上下文界定(Context bounds)、协变、逆变和不变

    1 泛型 1)如果我们要求函数的参数可以接受任意类型.可以使用泛型,这个类型可以代表任意的数据类型. 2)例如 List,在创建 List 时,可以传入整型.字符串.浮点数等等任意类型.那是因为 Li ...

  9. C#4.0泛型的协变,逆变深入剖析

    C#4.0中有一个新特性:协变与逆变.可能很多人在开发过程中不常用到,但是深入的了解他们,肯定是有好处的. 协变和逆变体现在泛型的接口和委托上面,也就是对泛型参数的声明,可以声明为协变,或者逆变.什么 ...

随机推荐

  1. Django学习笔记之URL与视图cookie和session

    cookie和session cookie:在网站中,http请求是无状态的.也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户.cookie的出现就是为了 ...

  2. 【DevExpress】GridView的RowClick事件禁用Checkbox选择的解决办法

    添加GridView的RowCellClick事件,代码如下 private void gvBoxMails_RowCellClick(object sender, DevExpress.XtraGr ...

  3. [ZZ] matlab中小波变换函数dwt2和wavedec2 系数提取函数appcoef2和detcoef2

    https://zhidao.baidu.com/question/88038464.html DWT2是二维单尺度小波变换,其可以通过指定小波或者分解滤波器进行二维单尺度小波分解. 而WAVEDEC ...

  4. form表单提交数据,页面必定会刷新,ajax提交数据不会刷新,做到悄悄提交,多选删除,ajax提交实例

    很多页面用到的模态对话框,如知明网站https://dig.chouti.com/的登录页都是模态对话框, 当点登录时,是用的ajax提交,因为输入错了信息,有返回消息,而页面没有刷新. jquery ...

  5. 编辑器-vim

    编辑器之神-vim vi简介 vi是“Visual interface”的简称,它在Linux上的地位就仿佛Edit程序在DOS上一样.它可以执行输出.删除.查找.替换.块操作等众多文本操作,而且用户 ...

  6. Spfa求最短路径

    spfa求最短路径,其思想就是遍历每一个点,将没有入队的点入队,从这个点开始不断修改能够修改的最小路径,直到队空.不过这里一个点可以重复入队. 这个需要有存图的基础--------->前向星存图 ...

  7. pyexecjs模块

    1,找到断点事件 2,浏览call stack 下面的代码,找到需要的值 3,F11进入方法内部 对于网站自己定义的方法,可以用py复制下来进行执行js N = function (a, b, c) ...

  8. C&C++类型定义typedef

    1.声明 1.1结构声明: struct { int n; double x,y; }; 1.2带结构标志的声明 struct point{ double x,y; }; 1.3定义结构类型 1.3. ...

  9. logging模块全总结

    Python之日志处理(logging模块)   本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四 ...

  10. C语言数据结构基础学习笔记——静态查找表

    查找:在数据集合中寻找满足某种条件的数据元素的过程称为查找. 查找表:用于查找的数据集合称为查找表,一般有以下操作:①查找是否在表中:②查找属性:③进行操作. 查找表又分为: ①静态查找表:只可以进行 ...