一、协变

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. Fiddler 延迟请求

    1.开启浏览器代理 2.fiddler设置要抓取的域名 3.设置fiddler代理端口 Tools->Options->Connections 4.设置接口延时 5.访问页面即可延时此接口

  2. Linux下编译成静态库和动态库,引入到项目中

    目录 配置全局变量 编译动态库和静态库: 动态库编译 静态库编译 AS mk 方式加载静态库和动态库 配置build.gradle 加载静态库方法 将libget.a考入到项目中 配置Android. ...

  3. Spring Boot学习日记11

    学习静态资源,和统一打包 WebJars是将web前端资源(js,css等)打成jar包文件然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理 拿到静态资源 http://loca ...

  4. ARouter路由解析

    目录介绍 01.原生跳转实现 02.实现组件跳转方式 2.1 传统跳转方式 2.2 为何需要路由 03.ARouter配置与优势 04.跨进程组件通信 4.1 URLScheme 4.2 AIDL 4 ...

  5. 为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.安全特性 在上篇文章中,我们了解到HTTP在通信过程中,存在以下问题: 通信使用明文(不加密),内容可能被窃听 不验证通信方的身份,因 ...

  6. uniapp热更新和整包更新思路

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 我们知道,在打包Android App之前,我们需要先通过HX生成打包资源.如果是通过cli创建的项目,则通过以下命令生成打包资源: ya ...

  7. verilog设计知识集合

    verilog设计知识集合 一.基本知识 verilog HDL,verilog硬件描述语言,可从上层到下层一直设计,使用一些列分层的模块来表示极其复杂的数字系统的语言.利用EDA工具将模块转化为网表 ...

  8. KingbaseES 实现 MySQL 函数 last_insert_id

    用户从mysql迁移到金仓数据库过程中,应用中使用了mysql函数last_insert_id()来获取最近insert的那行记录的自增字段值. mysql文档中关于函数的说明和例子: LAST_IN ...

  9. 使用OHOS SDK构建libsamplerate

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/libsndfile/l ...

  10. HMS Core分析服务智能运营6.5.1版本上线

    HMS Core分析服务智能运营6.5.1版本上线,三大"更"新,助力开发者提升运营体验. 1.活动效果更前置:支持受众预估,提前判断活动效果: 2.活动流程更规范:新增活动审核功 ...