深入了解装箱和拆箱

 我们将通过实际的例子以及ILDASM.exe工具去查看装箱和拆箱的过程(至于ILDASM.EXE的用法请查看MicroSoft的帮助).

    一::我们想看下装箱和拆箱的对象

        装箱:值类型=>引用类型.

        拆箱:引用类型=>值类型

        所以我们看到再整个装箱和拆箱的过程中设计到两种类型.值类型(原类型(SbyteByteShortUshortIntUintLongUlongCharFloatDoubleBoolDecimal)、枚举(enum)、结构(struct).引用类型(类,接口,数组,委托,字符串等).

    实例1:阅读下面的程序,说出程序中的装箱和拆箱操作.

using  System;
class  sample1
{
  
public   static   void  Main()
  {
    
int  i = 10 ;
    
object  obj = i;
    Console.WriteLine(i
+ " , " + ( int )obj);
  }

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


 

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

   实例二:我这里我列出两个例子,装箱和拆箱对程序性能的影响

ExpandedBlockStart.gif
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Collections;

namespace  Boxandunbox
{
    
class  Sample
    {
        
public   static   void  Main()
        {
            
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();
        }
    }
}

请看运行结果图

 

 

 
ExpandedBlockStart.gif
using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Collections;

namespace  Boxandunbox
{
    
class  Sample
    {
        
public   static   void  Main()
        {
            
// Code1#region  // Code1
            
// 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();
     #endregion
            
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();
        }
    }
}

结果如下图

 

 

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

 

 

转载于:https://www.cnblogs.com/purplefox2008/archive/2010/08/26/1808951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值