装箱/拆箱和类型转换有什么区别?
通常,这些术语似乎可以互换使用。
装箱是指将不可为空的值类型转换为引用类型,或者将值类型转换为它实现的某个接口(例如int
to IComparable<int>
)。此外,将基础值类型转换为可空类型也是一种装箱转换。(警告:关于这个主题的大多数讨论将忽略后两种类型的转换。)
例如,
int i = 5;
object o = i;
转换i
为类型的实例object
。
拆箱是指从实例object
或ValueType
到不可空值类型的显式转换,将接口类型转换为不可空值类型(例如,IComparable<int>
到int
)。此外,可空类型到基础类型的转换也是一种拆箱转换。(警告:关于这个主题的大多数讨论将忽略后两种类型的转换。)
例如,
object o = (int)5;
int i = (int)o;
将装箱的整数转换o
为类型的实例int
。
类型转换是将表达式显式转换为给定类型。因此
(type) expression
显式转换expression
为 类型的对象type
。
装箱和拆箱是类型转换的子集。装箱是将值类型视为引用类型的行为(在实践中,涉及将该值类型的内容(从堆栈)复制到堆并返回对该对象的引用)。这允许在需要兼容引用类型的任何地方传递值类型。它还允许对值类型执行虚方法调用和引用类型的其他功能。取消装箱是此操作的逆操作(从装箱对象中取回值类型)。
类型转换是用于从特定类型变量到另一个变量的任何类型转换的术语。这是一个更广泛的概念。
几分钟前,我回答了一个涵盖这种差异的相关问题。总而言之,我对 C# cast 运算符生成的不同类型的 IL 指令进行了分类:
box
IL 指令)和拆箱(unbox
IL 指令)dynamic_cast<Type>
在 C++ 中,使用castclass
IL 指令进行验证)static_cast<Type>
在 C++ 中,有大量 IL 指令用于原始类型之间的不同类型的转换)op_XXX
方法的方法调用)。装箱是将值类型(int、double、float、Guid 等)转换为引用类型(System.Object、System.String 等)的术语。执行此装箱操作会在堆上分配内存(垃圾收集器最终需要回收这些内存)。拆箱与此过程相反,将引用类型转换为值类型。
强制转换是采用一种类型(例如 System.Object)并将其视为另一种类型(例如 System.String)。
当您在 C# 中装箱时,您将其转换为另一种类型。不同之处在于它会在创建新的引用类型时分配额外的内存。
底线:装箱是一种特殊类型的转换,它将值类型转换为引用类型,这需要分配新的引用类型。
装箱/拆箱和类型转换是两种不同的操作,但是它们使用相同的语法。
只有当谈论它的人不知道真正发生了什么时,它们才可以互换使用......
装箱是将值类型作为对象存储在堆上,拆箱是从对象中读取值。您只能将值拆箱,因为它是确切的类型。
强制转换是指将一个基本类型转换为另一种基本类型(例如从 anint
到 a long
),或者当您更改引用的类型(例如 fromList<int>
到IEnumerable<int>
)时。
装箱意味着将值类型变量(即整数)转换为引用类型。拆箱是相反的,使用类型转换。简而言之,在 .NET 世界中,一切都源自“对象”类型。
例如(C# 示例):
int myInt = 0; // original variable (unboxed to begin with)
object boxed = myInt; // box it up
int myIntUnBoxed = (int)boxed; // and unbox it again using type casting
从中得出的结论是类型系统的统一,允许将值类型视为引用类型。本文对装箱/拆箱进行了更深入的了解。
拳击(隐式)
整数 = 12;
对象框=数字;
拆箱(显式)
对象框 = 12;
int number = (int)box;