[C# 基础知识系列]专题七: 泛型深入理解(一)
2013-05-14 10:04
851 查看
引言:
在上一个专题中介绍了C#2.0 中引入泛型的原因以及有了泛型后所带来的好处,然而上一专题相当于是介绍了泛型的一些基本知识的,对于泛型的性能为什么会比非泛型的性能高却没有给出理由,所以在这个专题就中将会介绍原因和一些关于泛型的其他知识。
一、泛型类型和类型参数
泛型类型和其他int,string一样都是一种类型,泛型类型有两种表现形式的:泛型类型(包括类、接口、委托和结构,但是没有泛型枚举的)和泛型方法。那什么样的类、接口、委托和方法才称作泛型类型的呢 ?我的理解是类、接口、委托、结构或方法中有类型参数就是泛型类型,这样就有类型参数的概念的。 类型参数 ——是一个真实类型的一个占位符(我想到一个很形象的比喻的,比如大家在学校的时候,一到中午下课的时候食堂人特别多的,所以很多应该都有用书本占位置的习惯的, 书本就相当于一个占位符,真真坐在位置上的当然是自己的,讲到占位置,以前听过我同学说,他们班有个很牛逼的MM,中午下完课的时候用手机占位子的,等它打完饭回来的时候手机已经不见, 当时听完我就和我同学说,你们班这位女生真牛逼的,后面我们就View Code
运行结果:
View Code
当使用非泛型的的ArrayList数组时,IL的代码如下(这里只是贴出了部分主要的中间代码,具体的大家可以下载示例源码用IL反汇编程序查看的):
在上面的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
在上一个专题中介绍了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
相关文章推荐
- [C# 基础知识系列]专题七: 泛型深入理解(一)
- [C# 基础知识系列]专题七: 泛型深入理解(一)
- [C# 基础知识系列]专题九: 深入理解泛型可变性
- [C# 基础知识系列]专题八: 深入理解泛型(二)
- [C# 基础知识系列]专题九: 深入理解泛型可变性
- [C# 基础知识系列]专题九: 深入理解泛型可变性
- 【转】[C# 基础知识系列]专题七:泛型深入理解(一)
- 【转】[C# 基础知识系列]专题八:深入理解泛型(二)
- [C#基础知识系列]专题八: 深入理解泛型(二) 推荐
- [C# 基础知识系列]专题八: 深入理解泛型(二)
- 【转】[C# 基础知识系列]专题九 :深入理解泛型可变性
- [C# 基础知识系列]专题九: 深入理解泛型可变性
- [C# 基础知识系列]专题八: 深入理解泛型(二)
- [C# 基础知识系列]专题七: 泛型深入理解(一)
- [C# 基础知识系列]专题八: 深入理解泛型(二)
- [C# 基础知识系列]专题九: 深入理解泛型可变性
- [C#基础知识系列]专题十七:深入理解动态类型 推荐
- [C#基础知识系列]专题:深入理解动态类型
- [C# 基础知识系列]专题十四:深入理解Lambda表达式
- [C# 基础知识系列]专题十四:深入理解Lambda表达式