在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。 协变保留分配兼容性,逆变则与之相反。

以下代码演示分配兼容性、协变和逆变之间的差异。

// 分配兼容性.
string str = "test";
// 将派生类型更高的对象分配给派生类型更低的对象
object obj = str; IEnumerable<string> strings = new List<string>();
// 用派生类型参数实例化的对象被分配给用派生类型参数实例化的对象。// 分配兼容性保持不变。
IEnumerable<object> objects = strings; // 逆变.
// 假设以下方法在类中:static void SetObject(object o) { }
Action<object> actObject = SetObject;
// 使用派生程度较低的类型参数实例化的对象被分配给使用派生程度较高的类型参数实例化的对象。// 分配兼容性被反转.
Action<string> actString = actObject;

对方法组的协变和逆变支持允许将方法签名与委托类型相匹配。 这样,不仅可以将具有匹配签名的方法分配给委托,还可以分配与委托类型指定的派生类型相比,返回派生程度更大的类型的方法(协变)或接受具有派生程度更小的类型的参数的方法(逆变)。 有关详细信息,请参阅委托中的变体 (C#)使用委托中的变体 (C#)

以下代码示例演示对方法组的协变和逆变支持。

static object GetObject() { return null; }
static void SetObject(object obj) { } static string GetString() { return ""; }
static void SetString(string str) { } static void Test()
{
// 协变. 委托将返回类型指定为对象,但可以指定返回字符串的方法。
Func<object> del = GetString; // 逆变. 委托将参数类型指定为字符串,但可以指定接受对象的方法。
Action<string> del2 = SetObject;
}

在 .NET Framework 4 或较新的 C# 中,支持在泛型接口和委托中使用协变和逆变,并允许隐式转换泛型类型参数。 有关详细信息,请参阅泛型接口中的变体 (C#)委托中的变体 (C#)《C#4.0新增功能03 泛型中的协变和逆变》

以下代码示例演示泛型接口的隐式引用转换。

IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;

如果泛型接口或委托的泛型参数被声明为协变或逆变,该泛型接口或委托则被称为“变体”。 凭借 C#,能够创建自己的变体接口和委托。 有关详细信息,请参阅创建变体泛型接口 (C#)委托中的变体 (C#)

相关主题

Title 说明
泛型接口中的变体 (C#) 讨论泛型接口中的协变和逆变,提供 .NET Framework 中的变体泛型接口列表。
创建变体泛型接口 (C#) 演示如何创建自定义变体接口。
在泛型集合的接口中使用变体 (C#) 演示 IEnumerable<T> 接口和 IComparable<T> 接口中对协变和逆变的支持如何帮助重复使用代码。
委托中的变体 (C#) 讨论泛型委托和非泛型委托中的协变和逆变,并提供 .NET Framework 中的变体泛型委托列表。
使用委托中的变体 (C#) 演示如何使用非泛型委托中的协变和逆变支持以将方法签名与委托类型相匹配。
对 Func 和 Action 泛型委托使用变体 (C#) 演示 Func 委托和 Action 委托中对协变和逆变的支持如何帮助重复使用代码。

C#2.0新增功能06 协变和逆变的更多相关文章

  1. c#4.0新特性之协变与逆变

    1.C#3.0以前的协变与逆变 如果你是第一次听说这个两个词,别担心,他们其实很常见.C#4.0中的协变与逆变[1](Covariance and contravariance)有了进一步的完善,主要 ...

  2. .NET 4.0中的泛型协变和逆变

    随Visual Studio 2010 CTP亮相的C#4和VB10,虽然在支持语言新特性方面走了相当不一样的两条路:C#着重增加后期绑定和与动态语言相容的若干特性,VB10着重简化语言和提高抽象能力 ...

  3. C#3.0新增功能06 对象和集合初始值设定项

    连载目录    [已更新最新开发文章,点击查看详细] 使用 C# 可以在单条语句中实例化对象或集合并执行成员分配. 对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属 ...

  4. .NET 4.0中的泛型的协变和逆变

    转自:http://www.cnblogs.com/jingzhongliumei/archive/2012/07/02/2573149.html 先做点准备工作,定义两个类:Animal类和其子类D ...

  5. 转载.NET 4.0中的泛型的协变和逆变

    先做点准备工作,定义两个类:Animal类和其子类Dog类,一个泛型接口IMyInterface<T>, 他们的定义如下:   public class Animal { } public ...

  6. Java协变、逆变、类型擦除

    协变.逆变 定义 Java中String类型是继承自Object的,姑且记做String ≦ Object,表示String是Object的子类型,String的对象可以赋给Object的对象.而Ob ...

  7. C#4.0新增功能03 泛型中的协变和逆变

    连载目录    [已更新最新开发文章,点击查看详细] 协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体 ...

  8. C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点

    C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点   第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它 ...

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

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

随机推荐

  1. CSS3 GENERATOR可以同时为一个元素完成border-radius、box-shadow、gradient和opacity多项属性的设置

    CSS3 GENERATOR可以同时为一个元素完成border-radius.box-shadow.gradient和opacity多项属性的设置 CSS3 GENERATOR 彩蛋爆料直击现场 CS ...

  2. Qt的模态对话框和非模态对话框 经常使用setAttribute (Qt::WA_DeleteOnClose)

    模态对话框就是指在子对话框弹出时,焦点被强行集中于该子对话框,子对话框不关闭,用户将无法操作其他的窗口.非模态相反,用户仍然可以操作其他的窗口,包括该子对话框的父对话框. 如果从线程角度来讲,模态对话 ...

  3. 开源玩家福利:十大Linux免费游戏

    假如当你考虑从Windows平台迁移至Linux平台时,“我能在Linux平台上游戏吗?”这类疑问正困扰着你,那么对此这有一个答案就是“快去Linux平台吧!”.感谢开源组织一直以来坚持不懈为Linu ...

  4. Delphi使用android的NDK是通过JNI接口,封装好了,不用自己写本地代码,直接调用

    一.Android平台编程方式:      1.基于Android SDK进行开发的第三方应用都必须使用Java语言(Android的SDK基于Java实现)      2.自从ndk r5发布以后, ...

  5. 获得QQ聊天输入框中的内容

    // 首先得到输入框的句柄.通过spy++这类工具分析,聊天窗体的类名为“#32770”// 但当前系统里不只一个类名为“#32770”的窗体,这就需要全体遍历一次.// 类名为“#32770”标题含 ...

  6. Ural_1169_Pairs

    此题略坑... 思路:把N个点分成m若干个联通子图,然后用m-1个桥把这m个联通子图连接起来即可. 若每个联通子图内部都是完全图也符合题意,但答案却是Wrong Answer,只有把每个联通子图内部当 ...

  7. JavaScript-DOM续

    一.路由的跳转 <body> <a href="#/course">课程</a> <a href="#/main"&g ...

  8. Linux基础(二)

    网卡的启动与关闭 ipup ens33 启动网卡 ifdown 关闭网卡 普通用户没有该权限 root用户,管理员,普通用户的权限 root 至高无上的 root用户所在的组是root组 ​ 管理员 ...

  9. spring boot 2.x 系列 —— spring boot 整合 servlet 3.0

    文章目录 一.说明 1.1 项目结构说明 1.2 项目依赖 二.采用spring 注册方式整合 servlet 2.1 新建过滤器.监听器和servlet 2.2 注册过滤器.监听器和servlet ...

  10. python基础--定义装饰器(内置装饰器)

    装饰器的定义: 装饰器本质上就是一个python函数,它可以让其它函数在不需要做任何代码改动的前提下增加额外的功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景中,比如-- >插入 ...