1. 是什么

    ===

1.1 协变

协变指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。如 string 到 object 的转换。多见于类型参数用作方法的返回值。

1.2 逆变

逆变指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型。如 object 到 string 的转换。多见于类型参数用作方法的输入值。

泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。

  1. 怎么理解

    ===

假如有一个 sub 子类和 parent 父类,我们可以很轻易地将 sub 转换成 parent,这是类型安全的,反之则不行。其实很好理解,子类必然具有相同或更多的属性和方法,所以转换成属性和方法可能更少的父类,只需要去除自身的部分属性和方法即可,这对编译器而言是可行的。反之,你怎么要求编译器为父类增加更多的成员呢。数组也继承了这一特性,对于一个string[]类型而言

理解了上述概念后,让我们来看看协变和逆变的概念,这里我们只谈谈关于接口可变性中的一些内容。以下我简单给出一个接口及其实现。

public interface IMyInTerface<T>
{
T Method1();
void Method2(T t);
} public class MyClass<T> : IMyInTerface<T>
{
public T Method1()
{
return default(T);
} public void Method2(T t)
{
Console.WriteLine(typeof(T).Name);
}
}

对应的调用方法代码如下

class Program
{
static void Main(string[] args)
{
// 协变演示
IMyInTerface<Sub> sub = new MyClass<Sub>();
Parent parent1 = sub.Method1(); // 逆变演示
IMyInTerface<Parent> parent2 = new MyClass<Parent>();
parent2.Method2(new Sub()); //// 协变演示
//IMyInTerface<Parent> parent = new MyClass<Parent>();
//Sub sub1 = parent.Method1(); //// 逆变演示
//IMyInTerface<Sub> sub2 = new MyClass<Sub>();
//sub2.Method2(new Parent()); Console.ReadKey();
}
}

以上调用代码都是正常的,但是当我们将上述代码的子类和父类的位置调换,换成上述注释中的代码,编译器则会报错。这便是违背了本文最重要的一个原则:类型转换中,对编译器而言只有子类到父类的转化才是安全的

比如说,我们不能把 parent 的实例 赋值给 sub1 ,我们也不能把 new Parent() 代替 Sub 传入 Method2() 方法。

所以这一切,都是命运石之门的选择呀。

也正是因此,为了防止开发者写出错误的代码,.net 设计者便用了协变和逆变(对应 out 和 in 关键字)来强制要求正确行为。也就是说,即使你想这么做,一旦你用了微软提供的 IEnumerable 等接口,你也无法进行错误的类型转换了。所以归根到底,协变和逆变只是一种约束而已,这种规范限制了你的泛型接口中要么只能有将类型参数当作返回值的协变相容方法(加了 out 关键字),要么只能有将类型参数当作输入值的逆变相容方法(加了 in 关键字)。

本文针对的是对协变和逆变存在部分理解但是仍然有些迷糊的开发者群体,而笔者也忙于新技术的理解和投入使用,有段时间没能分享所学所得,这次也只是花了十几分钟撷取了重要概念记录答疑,希望能帮到一部分人,以上就是我的期望了。假如有不理解的,欢迎在评论区贴出即可。

c# 协变和逆变的理解的更多相关文章

  1. 再谈对协变和逆变的理解(Updated)

    去年写过一篇博客谈了下我自己对协变和逆变的理解,现在回头看发现当时还是太过“肤浅”,根本没理解.不久前还写过一篇“黑”Java泛型的博客,猛一回头又是“肤浅”,今天学习Java泛型的时候又看到了协变和 ...

  2. 深入理解 C# 协变和逆变

    msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不够直白. 直白的理解: “协变” ...

  3. 【转】深入理解 C# 协变和逆变

    http://www.cnblogs.com/qixuejia/p/4383068.html 深入理解 C# 协变和逆变   msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程 ...

  4. 深入理解 C# 协变和逆变 (转载)

      深入理解 C# 协变和逆变 msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不 ...

  5. Scala教程之:深入理解协变和逆变

    文章目录 函数的参数和返回值 可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型:使用-表示逆变类型:非转化类型不需要添加标记. 假如我们定义一个cla ...

  6. C# 泛型的协变和逆变

    1. 可变性的类型:协变性和逆变性 可变性是以一种类型安全的方式,将一个对象当做另一个对象来使用.如果不能将一个类型替换为另一个类型,那么这个类型就称之为:不变量.协变和逆变是两个相互对立的概念: 如 ...

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

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

  8. c#的协变和逆变

    关于协变和逆变要从面向对象继承说起.继承关系是指子类和父类之间的关系:子类从父类继承,所以子类的实例也就是父类的实例.比如说Animal是父类,Dog是从Animal继承的子类:如果一个对象的类型是D ...

  9. 那些年搞不懂的"协变"和"逆变"

    博主之前也不是很清楚协变与逆变,今天在书上看到了有关于协变还是逆变的介绍感觉还是不太懂,后来看了一篇园子里面一位朋友的文章,顿时茅塞顿开.本文里面会有自己的一些见解也会引用博友的一些正文,希望通过本篇 ...

随机推荐

  1. vs2015安装出问题

    win7系统需要更新serverpage1包,更新完就ok了,ie不用升级到ie10

  2. 关于oracle数据库

    Oracle数据库是做什么的? oracle数据库和其他数据库一样,都是保存数据的,同时可以去查询,修改,删除等oracle和其他数据不一样的地方在于,它又复杂的机制可以保证在数据库服务器突然坏了的情 ...

  3. C/C++ 宏

    0. #define MALLOC(n, type) \ ( (type *) malloc((n)* sizeof(type))) 1. 宏可以像函数一样被定义,例如:    #define min ...

  4. tf.unstack\tf.unstack

    tf.unstack 原型: unstack( value, num=None, axis=0, name='unstack' ) 官方解释:https://tensorflow.google.cn/ ...

  5. SSH框架整合的其它方式

    --------------------siwuxie095 SSH 框架整合的其它方式 1.主要是整合 Spring 框架和 Hibernate 框架时,可以不写 Hibernate 核心配置文件: ...

  6. BIOS设置找不到设置U盘启动

    今天上午弄了好久,BIOS设置找不到设置U盘启动,后来改了一个选项突然就可以了,或许有时候是这个地方的问题 advanced bios features-->interrupt 19 captu ...

  7. Java 架构师

    “学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 1.能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超 ...

  8. JavaScript开发者的工具箱

    自从HTML5变得流行以来,整个Web平台取得了长足的进步,人们也开始将JavaScript视为一门能够创建复杂应用的语言.许多新的API纷纷浮现,而关于浏览器如何应用这些技术的文章也大量涌现. 作为 ...

  9. geoserver 问题解决

    GeoServer的8080端口被占用了怎么办?如何修改GeoServer的端口? GeoServer管理页面的登陆地址正常情况下为:http://localhost:8080/geoserver/w ...

  10. [BAT] 执行xcopy命令后出现Invalid num of parameters错误的解决办法

    如果是Windows下的命令行,对于有空格的文件路径要加引号,对于xcopy命令就是源路径和目标路径都要加引号 xcopy "C:\ppt" "D:\Program do ...