• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > C#4.0新特性之协变与逆变实例分析

C#4.0新特性之协变与逆变实例分析

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c#继承的特性,c#特性,c#6.0新特性,c#6新特性,c#语言特性等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本文实例讲述了C#4.0新特性的协变与逆变,有助于大家进一步掌握C#4.0程序设计。具体分析如下:

一、C#3.0以前的协变与逆变

如果你是第一次听说这个两个词,别担心,他们其实很常见。C#4.0中的协变与逆变(Covariance and contravariance)有了进一步的完善,主要是两种运行时的(隐式)泛型类型参数转换。简单来讲,所谓协变(Covariance)是指把类型从“小”升到“大”,比如从子类升级到父类;逆变则是指从“大”变到“小”,两者各有不同的条件和用途。下面的例子演示了C#3.0以前对协变与逆变支持 :

代码1

public class Animal { }
public class Cat : Animal { }

public delegate Animal AniHandler(Animal a);
public static Animal AniMethod(Animal a) { return null; }
public static Cat CatMethod(Object o) { return null; }

public static void TestCovariance()
{
  AniHandler handler1 = AniMethod;
  AniHandler handler2 = CatMethod;//这里是合法的
}

</div>

这里的CatMethod虽然不是严格满足委托AniHandler的签名,但它被用作AniHandler是合法的,在协变(Cat->Animal)和逆变(object->Animal)的作用下,委托指向的方法中,传入的参数可以是一个大的,宽泛的类型,而返回出来的结果可以是一个更小的,精确的类型(子类),因为它包含了更多的信息。注意这里是站在方法里面这样说的,而在调用者使用方法的角度,恰恰是相反的,在调用方法时,参数可以是一个“小”的子类,而返回值可以用作一个“大”的父类,如下面的调用是合法的:

object o = AniMethod(new Cat());

</div>

呵呵,听上去有点晕,现在我要试着把问题简洁地表达清楚。无论是协变还是逆变,它都是为了让这样一个非常合理的事实成立:如果提供的类型信息比所需要的类型信息多(而不是相等),那这当然是可以的。在代码1的例子中,AniHandler委托需要一个Animal作为返回值,但是我返给它一个Cat,Cat包含了Animal的所有特征,这当然是可以的,这就是协变;同时AniHandler需要一个Animal作为参数,为了让函数获得的信息比要求的多,我可以只要求传进来一个object,这也当然是可以的,这就是逆变。

二、C#4.0中的协变

我们先来看一下和谐的协变是如何发生的。C#4.0中的协变与C#3.0中的宽松委托非常类似,新的C#协变特征还体现在泛型接口或者泛型委托的类型参数上。还是以经典的Animal和Cat为例,在你看过上面代码1之后,既然Cat CatMethod()可以被用作Animal AniHandler,那么你完全有理由相信下面的代码在C#3.0中也是合法的:

代码3

delegate T THandler<T>();

static void Main(string[] args)
{      
  THandler<Cat> catHandler= () => new Cat();
  THandler<Animal> aniHandler = catHandler;//Covariance 
}

</div>

很遗憾,您错了,在C#3.0中,上面的代码不能通过编译,你会被告知发生错误!

时代进步了,现在在C#4.0的编译器是支持上面的写法的。你只需要在声明THandler的类型参数前加一个out关键字即可:

delegate T THandler<out T>();
</div>

单独的使用一个关键字而不是直接允许隐式转换也是为了类型安全的考虑。所以当你写下out的时候,就应该知道可能发生的Covariance。

三、C#4中的逆变

我们继续使用Animal和Cat的例子,在VS2008中,以下的代码不能通过编译:

代码5

delegate void THandler<T>(T t);  
public static void TestContravariance()
{
  THandler<Animal> aniHandler = (ani) => { };
  THandler<Cat> catHandler = aniHandler;
}

</div>

而在VS2010中,呃,同样不能。呵呵,其实就差一点点,这里如果在类型参数T前面加上关键字“in”,即delegate void THandler<in T>(T t);就可以实现Cat->Animal的Contravariance。

四、总结:

C#4中的协变和逆变使得泛型编程时的类型转换更加自然,不过要注意的是上面所说的协变和逆变都只作用于引用类型之间,而且目前只能对泛型接口和委托使用。一个T参数只能是in或者是out,你如果即想你的委托参数逆变又想返回值协变(如代码1所示),是做不到的。

相信本文所述对于大家更好的掌握C#4.0程序设计有一定的借鉴作用。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C# 6.0 新特性汇总
  • C#开发教程之利用特性自定义数据导出到Excel
  • C#特性 扩展方法
  • C#特性-对象集合初始化器介绍
  • C#4.0新特性之协变与逆变实例分析

相关文章

  • 2017-05-28C#遍历得到checkboxlist选中值和设置选中项的代码
  • 2017-05-28c#判断输入的是不是数字的小例子
  • 2017-05-28WinForm实现程序一段时间不运行自动关闭的方法
  • 2017-05-28C#获取路由器外网IP,MAC地址的实现代码
  • 2017-05-28C# 设计模式系列教程-桥接模式
  • 2017-05-28C#中Override关键字和New关键字的用法详解
  • 2017-05-28C#中进程的挂起与恢复
  • 2017-05-28c#(Socket)异步套接字代码示例
  • 2017-05-28详解C#设计模式编程中的模板方法模式使用
  • 2017-05-28c# 实现MD5,SHA1,SHA256,SHA512等常用加密算法源代码

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 用C#编写ActiveX控件(三)
    • C#之Expression表达式树实例
    • 解析如何使用反射调用类型成员 方法,字段,属性
    • C# WCF简单入门图文教程(VS2010版)
    • WinForm中KeyDown,KeyPress和KeyUp的顺序与区别解析
    • 使用mutex实现应用程序单实例运行代码分享
    • 使用代理模式来进行C#设计模式开发的基础教程
    • 基于c# 接口的实例详解
    • List<>中Find的用法小结
    • 基于C#实现网络爬虫 C#抓取网页Html源码

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有