您的位置:首页 > 编程语言 > C#

[C# 基础知识系列]专题七: 泛型深入理解(一)

2013-05-14 10:04 851 查看
引言:

  在上一个专题中介绍了C#2.0 中引入泛型的原因以及有了泛型后所带来的好处,然而上一专题相当于是介绍了泛型的一些基本知识的,对于泛型的性能为什么会比非泛型的性能高却没有给出理由,所以在这个专题就中将会介绍原因和一些关于泛型的其他知识。

一、泛型类型和类型参数

  泛型类型和其他int,string一样都是一种类型,泛型类型有两种表现形式的:泛型类型(包括类、接口、委托和结构,但是没有泛型枚举的)和泛型方法。那什么样的类、接口、委托和方法才称作泛型类型的呢 ?我的理解是类、接口、委托、结构或方法中有类型参数就是泛型类型,这样就有类型参数的概念的。 类型参数 ——是一个真实类型的一个占位符(我想到一个很形象的比喻的,比如大家在学校的时候,一到中午下课的时候食堂人特别多的,所以很多应该都有用书本占位置的习惯的, 书本就相当于一个占位符,真真坐在位置上的当然是自己的,讲到占位置,以前听过我同学说,他们班有个很牛逼的MM,中午下完课的时候用手机占位子的,等它打完饭回来的时候手机已经不见, 当时听完我就和我同学说,你们班这位女生真牛逼的,后面我们就View Code
运行结果:

View Code
当使用非泛型的的ArrayList数组时,IL的代码如下(这里只是贴出了部分主要的中间代码,具体的大家可以下载示例源码用IL反汇编程序查看的):



IL_001f:  ldloc.1
IL_0020:  ldloc.3
IL_0021:  box        [mscorlib]System.Int32
  IL_0026:  callvirt   instance int32 [mscorlib]System.Collections.ArrayList::Add(object)
IL_002b:  pop
IL_002c:  nop
IL_002d:  ldloc.3
IL_002e:  ldc.i4.1
IL_002f:  add




在上面的IL代码中,我用红色的标记的代码主要是在执行装箱操作(装箱过程肯定是要消耗的事件的吧, 就像生活中寄包裹一样,包装起来肯定是要花费一定的时间的, 装箱操作同样会,然而对于泛型类型就可以避免装箱操作,下面会贴出使用泛型类型的IL代码的截图)——这个操作也是影响非泛型的性能不如泛型类型的根本原因。然而为什么使用ArrayList类型在调用Add方法来向数组添加元素之前要装箱的呢?原因其实主要出在Add方法上的, 大家可以用Reflector反射工具查看ArrayList的Add方法定义,下面是一张Add方法原型的截图:



从上面截图可以看出,Add(objec value)需要接收object类型的参数,然而我们代码中需要传递的是int实参,此时就需要会发生装箱操作(值类型int转化为object引用类型,这个过程就是装箱操作),这样也就解释了为什么调用Add方法会执行装箱操作的, 同时也就说明泛型的高性能的好处。

下面是使用泛型List<T>的IL代码截图(从图片中可以看出,使用泛型时,没有执行装箱的操作,这样就少了装箱的时间,这样当然就运行的快了,性能就好了。):



四、小结

  说到这里本专题的内容也就介绍结束了,本专题主要是进一步介绍了泛型的其他内容的,由于篇幅的关于我将泛型的其他内容放在下一专题中,如果都在放在这个专题中内容会显得非常多,这样也不利于大家的消化和大家的阅读,所以我在下一个专题中继续介绍泛型的其他的一些内容。

下面先附上泛型专题中用到的所有Demo的源代码:http://files.cnblogs.com/zhili/GeneralDemo.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: