王朝网络
分享
 
 
 

C#学习笔记二:用实例深入理解装箱、拆箱

王朝c#·作者佚名  2006-01-08
宽屏版  字体: |||超大  

学习.NET的过程中,发现大多数的书都讲到了装箱(boxing)和拆箱(unboxing)的概念,至于为什么要理解装箱和拆箱?则总是一句话带过:优化程序的性能云云。至于为什么会对程序的性能产生影响,如何影响,我总感觉讲得并不透彻,当然也可能是我理解力有限。

这篇笔记,我并不打算对装箱和拆箱做全面的介绍,这些内容书上都有,csdn上也有很好的文章(请见kenli写的dotnet学习笔记一 - 装箱拆箱

http://www.csdn.net/Develop/Read_Article.asp?Id=19575),我只做简单的总结,并在此基础上引入两个例子,一个例子用ILDASM.EXE查看装箱和拆箱的过程,另外一个例子我编制一个简单例子分析正确理解装箱和拆箱对程序性能的影响。

由于在下面的例子和以后的例子我们将再次用到ILDASM,但不再给出详细的解释,因此给出MSDN关于反汇编语言的帮助信息,要查找汇编语言的命令,请在MSDN中.NET Framework/参考/类库/ System.Reflection.Emit 命名空间/OpCodes类中可以找到相关信息。

总结1:.NET中所有类型都是对象,所有类型的根是System.Object。

总结2:类型分为值类型(value)和引用类型(regerence type)。C#中定义的值类型包括:原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)。引用类型包括:类、数组、接口、委托、字符串等。

实例一:读下列程序,你能说出其中进行了几次装箱和拆箱的操作吗?

using System;

class sample1

{

public static void Main()

{

int i=10;

object obj=i;

Console.WriteLine(i+","+(int)obj);

}

}

其中发生了三次装箱操作和一次拆箱操作。第一次object obj=i;将i装箱;而Console.WriteLine方法用的参数是String对象,因此,i+","+(int)obj中,i需要进行一次装箱(转换成String对象),(int)obj将obj对象拆箱成值类型,而根据WriteLine方法,比较将(int)obj值装箱成引用类型。说起来这么复杂,大家看看ildasm.exe的反汇编结果(如下图),就很容易理解了。

注意图中红色圆圈的标识。

如果我们将Console.WriteLine(i+","+(int)obj);

改为: Console.WriteLine(obj+","+obj); 得到同样的效果,而其中仅进行一次装箱操作(object obj=i;),虽然这个程序并没有实际的意义,但是加深我们对概念的理解。

实例二:我这里我列出两个例子,装箱和拆箱对程序性能的影响不问自知。我的机器配置是P4 1.6A,512M内存。随后会列出测试的截图,你比我更快吗?当然是的?那么告诉我吧。:(

// 例子1:boxing1.cs

using System;

using System.Collections;

namespace test1

{

class Class1

{

static void Main(string[] args)

{

int count;

DateTime startTime = DateTime.Now;

ArrayList myArrayList = new ArrayList();

// 重复5次测试

for(int i = 5; i > 0; i--)

{

myArrayList.Clear();

// 将值类型加入myArrayList数组

for(count = 0; count < 5000000; count++)

myArrayList.Add(count); //装箱

// 重新得到值

int j;

for(count = 0; count < 5000000; count++)

j = (int) myArrayList[count]; //拆箱

}

// 打印结果

DateTime endTime = DateTime.Now;

Console.WriteLine("Start: {0}\nEnd: {1}\nSpend: {2}",

startTime, endTime, endTime-startTime);

Console.WriteLine("Push ENTER to return commandline...");

Console.ReadLine();

}

}

}

下图是boxing1.exe的测试结果:

// 例子2:boxing2.cs

using System;

using System.Collections;

namespace test2

{

class Class2

{

static void Main(string[] args)

{

int count;

ArrayList myArrayList = new ArrayList();

// 构造 5000000 字符串数组

string [] strList = new string[5000000];

for(count = 0; count < 5000000; count++)

strList[count] = count.ToString();

// 重复5次测试

DateTime startTime = DateTime.Now;

for(int i = 5; i > 0; i--)

{

myArrayList.Clear();

// 将值类型加入myArrayList数组

for(count = 0; count < 5000000; count++)

myArrayList.Add(strList[count]);

// 重新得到值

string s;

for(count = 0; count < 5000000; count++)

s = (string) myArrayList[count];

}

// 打印结果

DateTime endTime = DateTime.Now;

Console.WriteLine("Start: {0}\nEnd: {1}\nSpend: {2}",

startTime, endTime, endTime-startTime);

Console.WriteLine("Push ENTER to return commandline...");

Console.ReadLine();

}

}

}

下图是boxing2.exe的测试结果:

实例二说明:boxing1.cs的循环中包含一次装箱和一次拆箱(这里我均忽略两个程序打印时的装箱操作),boxing2.cs则没有相应的操作。当循环次数足够大的时候,性能差异是明显的。再次提醒你别忘了ILDASM.EXE这个工具哦,分别看看,才能一窥程序的本质。否则,粗看程序boxing2.cs比boxing1.cs多了不少代码,更多了一个5000000(5M)的循环,就以为boxing2会更慢。。。

另外一方面,装箱和拆箱对性能的影响更偏重于大型的程序和软件,这就是我用这么多循环的原因。但你能保证你不会进行大批量的数据处理吗?

MSDN上有更实用的例子:统计大量的英文单词,当然也更加复杂,故不在此详细讲解。

http://www.microsoft.com/china/msdn/voices/csharp03152001.asp

文章的结尾处,我想你应该测试一下你对装箱和拆箱的理解:(同样来自MSDN)

看看各种方案中是否进行了装箱和拆箱的操作,各有多少次。

// 方案 1

int total = 35;

DateTime date = DateTime.Now;

string s = String.Format("Your total was {0} on {1}", total, date);

// 方案 2

Hashtable t = new Hashtable();

t.Add(0, "zero");

t.Add(1, "one");

// 方案 3

DateTime d = DateTime.Now;

String s = d.ToString();

// 方案 4

int[] a = new int[2];

a[0] = 33;

// 方案 5

ArrayList a = new ArrayList();

a.Add(33);

// 方案 6

MyStruct s = new MyStruct(15);

IProcess ip = (IProcess) s;

ip.Process();

今天就到这里吧,我也是初学,望多多指教。什么?上面测试的标答?呵呵,你应该找得到的,找不到?我会贴在评论中。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有