C# – 装箱(box)与拆箱(unbox) 094

C# – 装箱(box)与拆箱(unbox) 0941)了解装箱拆箱的概念2)掌握什么情况下会发生装箱,拆箱操作(2-7)3)通过示例查看有无装箱拆箱操作的性能差别(查看消耗时间)装箱拆箱的定义:

大家好,欢迎来到IT知识分享网。

1)了解装箱拆箱的概念

2)掌握什么情况下会发生装箱,拆箱操作(2-7)

3)通过示例查看有无装箱拆箱操作的性能差别(查看消耗时间)

装箱拆箱的定义:

1) 装箱:将值类型转换为引用类型,是隐式进行的

2) 拆箱:将引用类型转换为值类型,是显示进行的

因为每进行一次装箱或拆箱操作都会涉及一次内存的拷贝动作,因此大量频繁地进行装箱拆箱的操作会大幅影响程序的性能

标准装箱拆箱

在C#中object类型是所有类型的基类,因此值类型,引用类型都可以赋值给object类型

//声明了值类型 n int n = 8; //进行了装箱操作 //将值类型 n 进行了隐式(自动)转换 //将其赋值给了引用类型的 o object o = n; //进行拆箱操作 //将引用类型的 o 进行了显示(强制)转换 //将其赋值给了 值类型的 m int m = (int)o; Console.WriteLine(m); Console.ReadKey();
C# - 装箱(box)与拆箱(unbox) 094

反编译查看底层的装箱拆箱操作

只进行类型转换而无装箱拆箱

////1 同是引用类型 ////将子类赋值给父类 //Person p = new Student(); ////这个是进行了显示类型转换,不叫拆箱 //Student stu = (Student)p; ////原因在于它们都是引用类型,因此 ////只存在类型转换的关系 ////int类型为什么可以装箱到object类型 ////但不能装箱到string类型或Person类型 ////原因在于:object类型是int类型的父类(值类型也继承自object) //2 通过方法将值类型转换为引用类型 int n = 10; //不是装箱,只是进行了隐式类型转换 string s1 = Convert.ToString(n); //不是拆箱,只是进行了隐式类型转换 //只是从意义上而不是从内存上进行转换 int m = int.Parse(s1); //原因在于:字符串类型与int类型在内存上不存在"交集", //根本无法进行类型转换,而object与int可以转换的原因是 //因为任何类型都是继承自object类型 可反编译在IL模式下查看是否有 box与unbox操作

拆箱时,必须使用装箱时的类型来拆箱

装箱的时候,使用什么类型来装箱,拆箱的时候还必须使用原来的类型来拆箱,否则会报异常:指定的转换无效

C# - 装箱(box)与拆箱(unbox) 094

使用原类型进行拆箱操作

 int n = 10; object obj = n; //进行了装箱 double d = (int)obj;//进行了拆箱 //只要保证拆箱的类型与装箱时的类型一样即可 //最后赋值给 double 的 d 只是进行了隐式类型转换 //与装箱拆箱操作无关 Console.WriteLine(d); //============================ //无法进行拆箱,会报异常:指定的转换无效 //装箱时类型为 int 拆箱时类型为 double double f = (double)obj; Console.WriteLine(f); Console.ReadKey();

方法重载时,参数有该类型的重载,不叫装箱拆箱

int n = 10; //只是进行了类型转换 //没有发生装箱操作 string m = n.ToString(); //没有发生拆箱操作 int num = Convert.ToInt32(m); Console.WriteLine(num); Console.ReadKey();

接口与值类型之间的装箱与拆箱

值类型也可以继承接口,如int32实现(继承的意思)了3个接口与两个泛型接口

int n = 8; //进行了装箱操作 IComparable ic = n; //进行拆箱操作 int m1 = (int)ic;//拆箱后赋值给了原类型变量 //拆箱后先进行了隐式类型转换 //然后赋值给了float类型的变量 float m2 = (int)ic; Console.WriteLine(m1 + " " + m2); Console.ReadKey();

进行字符串连接时也会发生装箱,拆箱操作

string s1 = "a"; string s2 = "b"; int n3 = 10;//装箱 float n4 = 9.9f;//装箱 double n5 = 99.9;//装箱 //Concat()将参数进行连接 //共进行了3次装箱操作 string result = string.Concat(s1, s2, n3, n4, n5); Console.WriteLine(result); Console.ReadKey();
C# - 装箱(box)与拆箱(unbox) 094

字符串连接会发生装箱操作

装箱拆箱消耗性能问题

通过向ArrayList与List集合中添加10万个数字查看有无装箱时消耗时间的差别

//声明时就设置好容量,可节省性能 int capacity = ; ArrayList arList = new ArrayList(capacity); List<int> list = new List<int>(capacity); Console.WriteLine("共进行 {0} 次的添加元素",capacity); Console.WriteLine("ArrayList集合 会发生装箱操作"); Stopwatch sw = new Stopwatch(); sw.Start();//开始计时 for (int i = 0; i < capacity; i++) { arList.Add(i); } sw.Stop(); Console.WriteLine("共消耗 {0} 毫秒", sw.ElapsedMilliseconds); Console.WriteLine(""); Console.WriteLine("List泛型集合 不会发生装箱操作"); sw.Reset();//重置对象 //sw.Restart();//重启对象 sw.Start();//开始计时 for (int i = 0; i < capacity; i++) { list.Add(i); } sw.Stop(); Console.WriteLine("共消耗 {0} 毫秒", sw.ElapsedMilliseconds); Console.ReadKey();
C# - 装箱(box)与拆箱(unbox) 094

两种集合所耗时间

使用集合时,尽量使用泛型集合,以减少操作时中间可能存在的消耗

小结:

1)装箱拆箱(以下以”此操作“代指)发生在引用类型与值类型之间

2)即使是值类型与引用类型如果转换方法有该类型作为参数,也不会发生此操作

3)接口与值类型,字符串连接上都会发生此操作

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/71216.html

(0)
上一篇 2024-06-11 11:45
下一篇 2024-06-24 20:26

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信