一、协变

C#协变是指在一些特定的情况下,可以将一个派生类型的实例赋值给其基类或接口类型的引用。这里的“派生类型”指的是从某个基类或接口继承并增加了新的成员的类型。

C# 4.0 引入了对协变和逆变的支持。其中,协变针对的是返回类型,逆变则针对参数类型。通过使用协变和逆变,可以使得某些代码更加简单、易读,并且减少需要编写的重复代码。

具体来说,协变的主要提升体现在以下方面:

  1. 委托类型的协变:在 C# 2.0 中,委托类型必须完全匹配,也就是说,委托类型的参数和返回类型必须与目标方法的参数和返回类型完全相同。但在 C# 3.0 中,引入了委托类型的协变功能,可以将一个返回类型为派生类型的方法赋值给一个返回类型为基类类型(或接口类型)的委托变量,这样可以避免显式地进行类型转换。例如:

    public delegate T MyDelegate<out T>();
    public class Animal { }
    public class Mammal : Animal { }
    public class Giraffe : Mammal { } // 协变: Giraffe 是 Mammal 的派生类, Mammal 是 Animal 的派生类
    MyDelegate<Giraffe> giraffe = () => new Giraffe();
    MyDelegate<Mammal> mammal = giraffe;
    MyDelegate<Animal> animal = giraffe;
  2. 泛型类型参数的协变:在 C# 4.0 中,可以使用 out 关键字来声明泛型接口或委托的类型参数是协变的。这样,就可以将一个泛型类型的实例赋值给其基类或接口类型的引用。例如:

    public interface IMyInterface<out T> { }
    public class Animal { }
    public class Mammal : Animal { } // 协变: Mammal 是 Animal 的派生类
    IMyInterface<Mammal> mammal = null;
    IMyInterface<Animal> animal = mammal;

总之,C#的协变功能使得代码更加简洁、清晰,并且提高了代码的可读性和可维护性。

二、逆变

C#逆变是指在一些特定的情况下,可以将一个基类或接口类型的引用赋值给其派生类型的实例。这里的“派生类型”指的是从某个基类或接口继承并增加了新的成员的类型。

C# 4.0 引入了对协变和逆变的支持。其中,协变针对的是返回类型,逆变则针对参数类型。通过使用协变和逆变,可以使得某些代码更加简单、易读,并且减少需要编写的重复代码。

具体来说,逆变的主要应用场景是:

  1. 委托类型的逆变:在 C# 2.0 中,委托类型必须完全匹配,也就是说,委托类型的参数和返回类型必须与目标方法的参数和返回类型完全相同。但在 C# 4.0 中,引入了委托类型的逆变功能,可以将一个接受基类类型(或接口类型)参数的方法赋值给一个接受派生类型参数的委托变量,这样可以避免显式地进行类型转换。例如:

    public delegate void MyDelegate<in T>(T arg);
    public class Animal { }
    public class Mammal : Animal { }
    public class Giraffe : Mammal { } // 逆变: Animal 是 Mammal 的基类, Mammal 是 Giraffe 的基类
    MyDelegate<Animal> animal = (a) => Console.WriteLine(a.GetType());
    MyDelegate<Mammal> mammal = animal;
    MyDelegate<Giraffe> giraffe = animal;
  2. 泛型接口类型参数的逆变:在 C# 4.0 中,可以使用 in 关键字来声明泛型接口的类型参数是逆变的。这样,就可以将一个基类或接口类型的引用赋值给其派生类型的实例。例如:

    public interface IMyInterface<in T> { }
    public class Animal { }
    public class Mammal : Animal { } // 逆变: Animal 是 Mammal 的基类
    IMyInterface<Animal> animal = null;
    IMyInterface<Mammal> mammal = animal;

总之,C#的逆变功能使得代码更加简洁、清晰,并且提高了代码的可读性和可维护性。

《c#高级编程》第4章C#4.0中的更改(八)——协变和逆变的更多相关文章

  1. javascript高级编程3第二章:在html中使用javascript

    2.1 <script>元素 向html页面中插入javascript的主要方法,就是使用<script>元素.这个元素被加入到正式的html规范中.html4.01为< ...

  2. ASP.NET MVC5 高级编程 第5章 表单和HTML辅助方法

    参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTT ...

  3. ASP.NET MVC5 高级编程 第3章 视图

    参考资料<ASP.NET MVC5 高级编程>第5版 第3章 视图 3.1 视图的作用 视图的职责是向用户提供界面. 不像基于文件的框架,ASP.NET Web Forms 和PHP ,视 ...

  4. ASP.NET MVC5 高级编程 第2章 控制器

    参考资料<ASP.NET MVC5 高级编程>第5版 第2章 控制器 控制器:响应用户的HTTP 请求,并将处理的信息返回给浏览器. 2.1 ASP.NET MVC 简介 MVC 模式中的 ...

  5. UNIX环境高级编程 第8章 进程控制

    本章是UNIX系统中进程控制原语,包括进程创建.执行新程序.进程终止,另外还会对进程的属性加以说明,包括进程ID.实际/有效用户ID. 进程标识 每个进程某一时刻在系统中都是独一无二的,它们之间是用一 ...

  6. 【读书笔记】C#高级编程 第五章 泛型

    (一)泛型概述 泛型不仅是C#编程语言的一部分,而且与程序集中的IL代码紧密地集成.泛型不仅是C#语言的一种结构,而且是CLR定义的.有了泛型就可以创建独立于被包含类型的类和方法了. 1.性能 泛型的 ...

  7. 【读书笔记】C#高级编程 第六章 数组

    (一)同一类型和不同类型的多个对象 如果需要使用同一类型的多个对象,就可以使用数组或集合(后面章讲). 如果需要使用不同类型的多个对象,可以使用Tuple(元组)类型. (二)简单数组 如果需要使用同 ...

  8. 第四章 在MVC4.0中对脚本以及样式表的引用变化

    原文:http://www.cnblogs.com/xdotnet/archive/2012/07/21/aspnet40_webpage20.html 一.可以直接使用“~”,而无需使用Href对象 ...

  9. C#高级编程第1章-.NET体系结构

    内容提要: (1)编译和运行面向对象.NET代码 (2)IL/MSIL(Microsoft Intermediate Language)中间语言的优点 (3)值类型与引用类型 (4)数据类型化 (5) ...

  10. C#高级编程第2章-核心C#

    内容提要: 声明变量:变量的初始化和作用域:C#的预定义数据类型:在C#程序中使用条件语句.循环和跳转语句指定执行流:枚举:名称空间: Main()方法:基本命令行C#编译器选项:使用System.C ...

随机推荐

  1. RocketMQ为什么这么快?我从源码中扒出了10个原因!

    大家好,我是三友~~ RocketMQ作为阿里开源的消息中间件,深受广大开发者的喜爱 而这其中一个很重要原因就是,它处理消息和拉取消息的速度非常快 那么,问题来了,RocketMQ为什么这么快呢? 接 ...

  2. [VueJsDev] 快速入门 - vscode 插件推荐

    [VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html Vscode 插件推荐 ::: details 目录 目录 ...

  3. 单词本z ambition 雄心 amb = ab = about = around = 环绕

    ambition 雄心 amb = ab = about = around = 环绕 it = go = 走 ion 名词 重点是 amb 环绕 这里是抽象含义 表示内心向外扩展 所以是雄心 ambu ...

  4. vscode 函数注释方法 输入 /** 回车 自动就出来了

    vscode 函数注释方法 输入 /** 回车 自动就出来了

  5. linux 服务器 执行命令挂起 nohup 改用 pm2

    nohup http-server -p 80 & nohup完要 exit 退出,不能直接关! nohup完要 exit 退出,不能直接关! nohup完要 exit 退出,不能直接关! 重 ...

  6. arch安装deep-wine-wechat时,跳过md5检测的方法

    yay -S --mflags --skipinteg deepin-wine-wechat 这条命令是的我们跳过了md5检测! 微信的安装位置:C:\Program Files\Tencent\We ...

  7. 基于python源码的啸叫抑制算法解析

    一 原理解析 从下图一中可以看出,该算法的原理也是先检测出来啸叫,然后通过陷波器来进行啸叫抑制的,和笔者以前分析的所用方法基本耦合. ​   二 源码分析   函数PAPR:计算峰值功率和平均功率的比 ...

  8. PAT 甲级【1015 Reversible Primes】

    考察素数判断 考察进制转换 import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTok ...

  9. vue3中使用simple-keyboard实现虚拟键盘(带中文切换数字键盘)

    效果图 官网 simple-keyboard官网:https://hodgef.com/simple-keyboard/ 打不开的话请用魔法 不足 中文语言包支持度不够.不过自己可以找语言包替换 依赖 ...

  10. MyBatis中的association与collection应用

    MyBatis中的association与collection应用 在使用 MyBatis进行数据库操作时,经常会遇到需要处理对象之间的关联关系和集合映射的情况.为了更好地实现对象关系映射,MyBat ...