首页 《Effective C#》之减少装箱和拆箱

《Effective C#》之减少装箱和拆箱

举报
开通vip

《Effective C#》之减少装箱和拆箱《EffectiveC#》之减少装箱和拆箱2007-08-1211:00作者:愚翁出处:天极Yesky软件频道责任编辑:方舟为了便于文章的开展,首先介绍装箱(Boxing)和拆箱(Unboxing)这两个名词。.Net的类型分为两种,一种是值类型,另一种是引用类型。这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上。那么如果要把一个值类型数据放到堆上,就需要装箱操作;反之,把一个放在堆上的值类型数据取出来,则需要进行拆箱操作。例如,对于如下简单的装箱和拆箱操作语句。inti=123;object...

《Effective C#》之减少装箱和拆箱
《EffectiveC#》之减少装箱和拆箱2007-08-1211:00作者:愚翁出处:天极Yesky软件频道责任编辑:方舟为了便于文章的开展,首先介绍装箱(Boxing)和拆箱(Unboxing)这两个名词。.Net的类型分为两种,一种是值类型,另一种是引用类型。这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上。那么如果要把一个值类型数据放到堆上,就需要装箱操作;反之,把一个放在堆上的值类型数据取出来,则需要进行拆箱操作。例如,对于如下简单的装箱和拆箱操作语句。inti=123;objectobj=i;//Boxingif(objisint)intj=(int)obj;//Unboxing为了,更好的诠释装箱和拆箱操作,我借用MSDN关于“Boxing”的解释图,具体如下。明白了这两名词的意思,现在说说为什么要减少装箱和拆箱操作。原因有两个,主要是关于效率:一个就是对于堆的操作效率比较低;另一个就是对于堆上分配的内存资源,需要GC来回收,从而降低程序效率。考虑到这两点因素,那么需要在程序中减少装箱和拆箱操作。如何减少呢,涉及到这两个操作比较多的是,格式化输出操作,例如:String.Format,Console.WriteLine之类的语句。例如:Console.WriteLine("Numberlist:{0},{1},{2}",1,2,3);对于“1,2,3”来说,相当于前面的“123”一样,需要经过装箱和拆箱两个操作。那么如何避免呢,其实只要向WriteLine传递引用类型数据即可,也就是按照如下的方式。Console.WriteLine("Numberlist:{0},{1},{2}", 1.ToString(),2.ToString(),3.ToString());由于“1.ToString()”的结果是String类型,属于引用类型,因此不牵扯装箱和拆箱操作。其次,牵扯到装箱和拆箱操作比较多的就是在集合中,例如:ArrayList或者HashTable之类。把值类型数据放到集合中,可能会出现潜在错误。例如:publicstructPerson{privatestring_Name;publicstringName{get{return_Name;}set{_Name=value;}}publicPerson(stringPersonName){_Name=PersonName;}publicoverridestringToString(){return_Name;}}//UsingthepersoninacollectionArrayListarrPersons=newArrayList();Personp=newPerson("OldName");arrPersons.Add(p);//Trytochangethenamep=(Person)arrPersons[0];p.Name="NewName";Debug.WriteLine(((Person)arrPersons[0]).Name);//It's"OldName"这个问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 其实在前面的文章中已经讲过了。有人可能会说,是否可以按照如下的方式去修改呢。((Person)arrPersons[0]).Name="NewName";//Can'tbecompiled很不幸,如上操作不能通过编译。为什么呢,对于“((Person)arrPersons[0])”来说,是系统用一个临时变量来接收拆箱后的值类型数据,那么由于值类型是分配在栈上,那么操作是对实体操作,可是系统不允许对一个临时值类型数据进行修改操作。//UsingthepersoninacollectionArrayListarrPersons=newArrayList();Personp=newPerson("OldName");arrPersons.Add(p);//Trytochangethenamep=(Person)arrPersons[0];p.Name="NewName";arrPersons.RemoveAt(0);//RemoveolddatafirstarrPersons.Insert(0,p);//AddnewdataDebug.WriteLine(((Person)arrPersons[0]).Name);//It's"NewName"其实,这样操作会产生过多装箱和拆箱操作。那么更好的方法,可以通过接口来完成,从而减少装箱和拆箱操作。对于这个例子的接口实现应该如下。publicinterfaceIPersonName{stringName{get;set;}}publicstructPerson:IPersonName{privatestring_Name;publicstringName{get{return_Name;}set{_Name=value;}}publicPerson(stringPersonName){_Name=PersonName;}publicoverridestringToString(){return_Name;}}//UsingthepersoninacollectionArrayListarrPersons=newArrayList();Personp=newPerson("OldName");arrPersons.Add(p);//Changethename((IPersonName)arrPersons[0]).Name="NewName";Debug.WriteLine(((Person)arrPersons[0]).Name);//It's"NewName"很多人就问,为什么值类型不能修改,即((Person)arrPersons[0]).Name="NewName";//Can'tbecompiled而如上的接口类型就能修改呢,即((IPersonName)arrPersons[0]).Name="NewName";这是由于产生的临时变量的类型不同,前者已经在前面进行说明了,后者由于产生的临时变量的类型为IPersonName,属于引用类型,那么相当于临时变量就是原对象的引用,那么对于对于它的修改会直接修改到原对象,因此是可以的。可以说这里的不同本身在于产生临时对象的类型不同,从而造成本质的区别。通过接口来改写,这样就减少了装箱和拆箱操作,同时也保证了修改的正确性。不过要注意的是,这里接口对于的是引用类型,如果接口访问的或者返回的是值类型,那么用接口虽说能实现了,但是对于装箱和拆箱操作来说,并没有减少。对于装箱和拆箱操作来说,基本上就讲完了,只要记住频繁装箱和拆箱操作会降低程序效率,因此在编写的时候要尽量避免。
本文档为【《Effective C#》之减少装箱和拆箱】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_686908
暂无简介~
格式:doc
大小:24KB
软件:Word
页数:8
分类:
上传时间:2022-07-25
浏览量:1