什么是装箱拆箱

值类型与引用类型

在 C# 中,数据类型可以分为两种主要的类别:值类型(Value Types)和引用类型(Reference Types)。这两者在内存中的存储和传递方式有很大的区别。

数据类型 基本特点 内置的值类型 特殊注意事项
值类型
(Value Types)
存储的是实际的数据值。
直接存储在栈上(或内联在包含它们的对象内)。
当将一个值类型赋值给另一个值类型时,将复制整个值。
所有的数值类型(int、float、double,等等)。
字符类型(char)。
布尔类型(bool)。
结构体(struct)。
值类型的变量直接包含其数据。
值类型的默认值可以是它的零值(0、0.0、'\0' 等)。
引用类型
(Reference Types)
存储的是对象的引用(内存地址)。
对象存储在堆上,而引用存储在栈上(或者在对象内部,具体取决于情况)。
赋值操作只会复制引用,而不是整个对象。
所有的类(class)。
字符串(string)。
接口(interface)。
委托(delegate)。
引用类型的变量存储的是对象的地址。
对象的生存周期由垃圾回收器管理。
默认值是 null。

区别总结:
值类型的变量包含实际的数据值,而引用类型的变量包含对象的引用。
值类型存储在栈上,而引用类型存储在堆上,通过引用访问。
值类型的复制会复制整个数据,而引用类型的复制只是复制引用,不涉及数据的复制。
值类型的变量可以直接操作其值,而引用类型的变量需要通过引用访问对象的成员。
在选择使用值类型还是引用类型时,通常要考虑到内存占用、性能和语义等因素。例如,对于小型简单的数据,值类型可能更合适;而对于大型对象或需要在多处共享的数据,引用类型可能更为适用。

装箱和拆箱

装箱(Boxing)和拆箱(Unboxing)是与值类型和引用类型之间的相互转换有关的两个概念。在C#中,这两个操作涉及到值类型与引用类型的相互转换。

装箱(Boxing):

定义:装箱是将值类型(比如int, char, double等)转换为对应的引用类型(通常是object或System.ValueType的派生类)的过程。
实现:这个过程会将值类型的值包装在一个引用类型的对象中。
示例:

int i = 42; // 值类型
object obj = i; // 装箱

拆箱(Unboxing):

定义:拆箱是将引用类型转换为对应的值类型的过程。
实现:这个过程会从包装对象中提取值类型的值。
示例:

object obj = 42; // 装箱
int i = (int)obj; // 拆箱

性能影响:

装箱:会导致额外的内存分配,因为值类型需要在堆上创建一个对象。这可能会对性能产生影响,特别是在循环或对性能要求较高的代码中。
拆箱:也会导致一些性能开销,因为它需要将引用类型转换为值类型,并且可能涉及一些类型检查。
避免装箱和拆箱:

为了避免装箱和拆箱的性能开销,可以使用泛型类型,例如List,而不是ArrayList,以避免不必要的装箱。

List<int> list = new List<int>();
list.Add(42); // 没有装箱
int value = list[0]; // 没有拆箱

总的来说,装箱和拆箱是在值类型和引用类型之间进行转换的过程。在高性能和资源敏感的情况下,应当尽量避免不必要的装箱和拆箱操作。

posted @ 2023-10-04 21:09  二声  阅读(75)  评论(0编辑  收藏  举报