在实际项目中,尽量的减少使用装箱和拆箱。或者采用泛型的方法来进行数据的类型转换。
装箱和取消装箱过程需要进行大量的计算。对值类型进行装箱时,必须分配并构造一个全新的对象。次之,取消装箱所需的强制转换也需要进行大量的计算。有效的减少装箱与拆箱操作是对性能提高的一个好的途径。为此微软公司在.NET中提供了泛型来解决装箱和拆箱引起的性能问题。下面笔者通过一段简单的代码来说明这个问题,代码如下所示。
namespace MyConsole
{
class UnboxPerformance
{
/*将5000000条记录写入到ArrayList并将数据在读取出来的工作做5编
其中写入和读取ArrayList的工作就是装箱拆箱的工作
最后计算出执行这个方法所消耗的时间*/
private static void RunUnbox()
{
int count;
DateTime startTime = DateTime.Now;
ArrayList myArrayList = new ArrayList();
List<int> myTlist = new List<int>();
for (int i = 5; i > 0; i--) //重复5次测试
{
myArrayList.Clear();
for (count = 0; count < 5000000; count++) //将值类型加入myArrayList数组
myArrayList.Add(count); //装箱
int j; //重新得到值
for (count = 0; count < 5000000; count++)
j = (int)myArrayList[count]; //拆箱
}
DateTime endTime = DateTime.Now;
Console.WriteLine("使用装箱拆箱的数组-- 开始时间 {0} 结束时间 {1}
花费时间 {2}", startTime, endTime, endTime - startTime);
} //输出结果
/*将5000000条记录写入到泛型List集合中并将数据在读取出来的工作做5编
其中写入和读取List集合的工作不需要装箱与拆箱
最后计算出执行这个方法所消耗的时间*/
private static void RunNoUnbox()
{
int count;
DateTime startTime = DateTime.Now;
List<int> myTlist = new List<int>();
for (int i = 5; i > 0; i--) //重复5次测试
{
myTlist.Clear();
for (count = 0; count < 5000000; count++) //将值类型加入泛型数组
myTlist.Add(count);
int j; //重新得到值
for (count = 0; count < 5000000; count++)
j = myTlist[count];
}
DateTime endTime = DateTime.Now;
Console.WriteLine("使用泛型 -- 开始时间 {0} 结束时间 {1} 花费时间 {2}",
startTime, endTime, endTime - startTime);
} //输出结果
static void Main(string[] args)
{
RunUnbox(); //调用装箱拆箱的RunUnbox方法。
RunNoUnbox(); //调用使用泛型的RunNoUnbox方法。
Console.WriteLine("请输入任意键,结束运行");
Console.ReadLine();
}
}
}
代码运行的结果如下所示。
使用装箱拆箱的数组 -- 开始时间 2009-05-31 16:41:15 结束时间 2009-05-31 16:41:27
花费时间00:00:11.7343750
使用泛型数组 -- 开始时间 2009-05-31 16:41:27 结束时间 2009-05-31 16:41:28
花费时间00:00:01.1406250
由运行结果可以发现,即使进行同样的操作,使用装箱拆箱是使用泛型数值所花费时间的10倍。
【答案】
CLR将值类型的数据“包裹”到一个匿名的托管对象中,并将此托管对象的引用放在Object类型的变量中,这个过程称为“装箱(Boxing)”,拆箱是装箱的逆过程。对于装箱和拆箱对性能影响的解决办法是在程序中大量使用泛型进行替代。