当前位置:  编程技术>.net/c#/asp.net

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

    来源: 互联网  发布时间:2014-11-03

    本文导语:  本文实例讲述了C#4.0新特性的协变与逆变,有助于大家进一步掌握C#4.0程序设计。具体分析如下: 一、C#3.0以前的协变与逆变 如果你是第一次听说这个两个词,别担心,他们其实很常见。C#4.0中的协变与逆变(Covariance and contravar...

本文实例讲述了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;//这里是合法的
}

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

object o = AniMethod(new Cat());

呵呵,听上去有点晕,现在我要试着把问题简洁地表达清楚。无论是协变还是逆变,它都是为了让这样一个非常合理的事实成立:如果提供的类型信息比所需要的类型信息多(而不是相等),那这当然是可以的。在代码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();

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

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

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

delegate T THandler();

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

三、C#4中的逆变

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

代码5

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

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

四、总结:

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

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


    
 
 

您可能感兴趣的文章:

 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Oracle 11g 新特性 Flashback Data Archive 使用实例
  • Java8新特性lambda表达式有什么用(用法实例)
  • HTML5介绍及其特性
  • 网站新特性展示库 IntroJs
  • nginx服务器基本特性及使用技巧
  • Java 的特性切换实现 Togglz
  • Docker技术使用场景主要特性等相关资源整理
  • 请问谁有《Java 2核心技术 卷2:高级特性》中多线程(第一章)的内容?
  • Oracle 12c的九大最新技术特性介绍
  • PHP6 中可能会出现的新特性预览
  • mongodb 3.0下载安装、配置及mongodb最新特性、基本命令教程详细介绍
  • ************请问何处有《JAVA核心技术2:高级特性》下载?必给分!
  • 哪里有<Java 2核心技术 2 高级特性>下载?
  • jdk1.4有什么新特性或者改进呢?
  • 请问有关MAP,SET,LIST的定义,特性,要考scjp拉,书上又不清楚
  • java 中有一条特性
  • 我所希望的Java的跨平台特性及兼容性。
  • 即将推出的 Ubuntu 8.10 服务器版的新特性
  • 我现在刚刚学到JAVA的线程和socket,请问《JAVA 2宝典》和《JAVA核心技术卷2:高级特性》哪本书讲得比较好?
  • 如何处理此错误:java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]没有执行可选特性
  • 谁能把java2核心高级特性的源代码mail一份给我或者给我一个能在www.phptr.com下载的password
  • ThinkPHP3.1新特性之对分组支持的改进与完善概述
  • 为什么 java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]没有执行可选特性


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3