脚踏实地学C#3-装箱和拆箱
2024-08-30 09:13:36
装箱:一种接受值类型的值,根据这个值在堆中创建一个完整的引用类型对象并返回对象的引用(堆地址)的隐式转换
int i_number = 2; //在栈中声明int类型i_Number变量并初始化
object o_number = null; //在栈中声明object类型的o_Number变量并初始化值为null,不在堆中分配内存
o_number = i_number; //装箱过程 如下图所示①→②→③
Console.WriteLine(o_number);
装箱过程:1.在托管堆分配好内存,分配的内存量是值类型的字段需要的内存量(类型对象指针和同步索引块);
2.值类型的字段复制到新分配的堆内存;
3.将新分配的堆地址放入栈中的变量内;
拆箱:将装箱的对象转换为值类型的过程(显示转换)
object o_Number = 1; //装箱
int i_Number = (int)o_Number; //拆箱
Console.WriteLine(i_Number);
拆箱过程:1.获取已装箱的对象各个字段的地址;
2.将字段包含的值复制到值类型的实例中;
装箱和拆箱测试
class Program
{
private static void Main(string[] args)
{
ValueTypeTestMethod();
Console.ReadKey();
}
private static void ValueTypeTestMethod()
{
const int count = 10000000; //循环的次数
using (new OperationTimer("List<int> Type(int)"))
{
List<int> list = new List<int>();
for (int i = 0; i < count; i++)
{
list.Add(i); //泛型不装箱
int x = list[i]; //不拆箱
}
list = null;
}
using (new OperationTimer("ArrayList Type(int)"))
{
ArrayList arrayList = new ArrayList();
for (int i = 0; i < count; i++)
{
arrayList.Add(i); //会进行装箱
int x = (int)arrayList[i]; //进行拆箱
}
arrayList = null;
}
}
}
internal sealed class OperationTimer : IDisposable
{
private long m_StartTime;
private string m_MSG;
private int m_CollectionCount;
public OperationTimer(String msg)
{
PrepareForOperation(); //强制垃圾回收
m_MSG = msg;
m_CollectionCount = GC.CollectionCount(0);
m_StartTime = Stopwatch.GetTimestamp();
}
public void Dispose()
{
Console.WriteLine("{0,6:###.00} seconds (GC={1,3}) {2}", (Stopwatch.GetTimestamp() - m_StartTime) / (double)Stopwatch.Frequency, GC.CollectionCount(0) - m_CollectionCount, m_MSG);
}
private static void PrepareForOperation()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
集合 | List<int> | ArrayList | ||
---|---|---|---|---|
时间(s) | 垃圾回收次数 | 时间(s) | 垃圾回收次数 | |
64位程序 | .20 | 3 | 1.37 | 44 |
32位程序 | .22 | 3 | 1.57 | 23 |
注意:从上面测试看出List<int>和ArrayList在所耗时间和垃圾回收区别都是在很大的,所以用泛型List<int>代替ArrayList是一个很好的习惯!同时也避免在循环中大量的装箱和拆箱操作;
最新文章
- bootstrap常用的定义风格
- JavaScript变量——栈内存or堆内存
- Hibernate——主键配置
- 用Keytool和OpenSSL生成和签发数字证书
- 读《我是一只IT小小鸟》有感
- Linux-sed用法(2)
- composer的create-project安装php框架laravel for mac教程
- 整数转字符与字符转整数的C系统函数
- mvp框架
- BZOJ 1935: [Shoi2007]Tree 园丁的烦恼( 差分 + 离散化 + 树状数组 )
- SAP ABAP规划 SY-REPID与SY-CPROG差额
- FFmpeg源代码简单分析:av_write_frame()
- 《http权威指南》读书笔记16
- 如何使用微信web开发者工具调试企业微信
- oracle授权表权限给用户
- 从零开始学 Web 之 DOM(七)事件冒泡
- uigetfile的用法(批量读取图片)
- SRM473
- linux下的yum命令详细介绍
- idea中,war 与 war exploded 区别
热门文章
- uitableview使用reloaddata不管用
- sublime正则替换
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 【转】
- Net调用非托管代码(P/Invoke与C++InterOP) [转]
- 淘宝HSF 框架使用 总结
- 一起talk C栗子吧(第八十四回:C语言实例--使用信号进行进程间通信一)
- ios You app information could not be saved. Try again. If the problem persists, contact us
- windows程序设计——飞机大战笔记(Access数据库的使用)
- UITableView 自带编辑删除 自己定义button
- kubernetes之故障现场二,节点名称冲突