装箱/拆箱与类型转换之间有什么区别?
通常,这些术语似乎可以互换使用。
装箱/拆箱与类型转换之间有什么区别?
通常,这些术语似乎可以互换使用。
Answers:
拳击是指转换不可为空值类型的成引用类型或值类型的一些接口,它实现(说的转化int
到IComparable<int>
)。此外,基础值类型到可空类型的转换也是装箱转换。(注意:关于此主题的大多数讨论都将忽略后两种转换。)
例如,
int i = 5;
object o = i;
转换i
为type的实例object
。
拆箱是指显式转换从实例object
或ValueType
到一个不可为空值类型,接口类型的转换到非可空值类型(例如,IComparable<int>
至int
)。此外,可为空的类型到基础类型的转换也是拆箱转换。(注意:关于此主题的大多数讨论都将忽略后两种转换。)
例如,
object o = (int)5;
int i = (int)o;
将装箱的整数转换o
为type的实例int
。
类型转换是将表达式显式转换为给定类型。从而
(type) expression
显式转换expression
为类型的对象type
。
Nullable<T>
类型。将值类型强制转换为Nullable<T>
(aka T?
)不是装箱/拆箱的示例,因为未创建引用类型。例如int? x = 5
是一个类型转换,不是拳击的一个例子。
装箱和拆箱是类型转换的子集。装箱是将值类型视为引用类型的行为(实际上,这涉及将值类型的内容(从堆栈中)复制到堆中,并将引用返回给该对象)。这允许在期望兼容的引用类型的任何地方传递值类型。它还允许对值类型执行虚拟方法调用和引用类型的其他功能。取消装箱是此操作的相反操作(从装箱的对象中取回值类型)。
类型转换是用于从特定类型的变量到另一类型的任何类型的转换的术语。这是一个更广泛的概念。
几分钟前,我回答了一个有关这一区别的相关问题。总而言之,我对C#类型转换运算符生成的不同类型的IL指令进行了分类:
box
IL指令)和拆箱(unbox
IL指令)dynamic_cast<Type>
C ++中一样,使用castclass
IL指令进行验证)static_cast<Type>
C ++中一样,对于基本类型之间的不同类型的转换,有很多IL指令)op_XXX
方法的方法调用)。int*
,它仍然是不可变的。堆上的内存实际上并不是4个字节。它具有类型信息并在其上调用虚拟方法:因此object o = 5; string s = o.ToString();
起作用。这是不可能的简单的int*
。在C ++中,这涉及vtables,而拳击也必须处理这些东西。
装箱是用于将值类型(int,double,float,Guid等)转换为引用类型(System.Object,System.String等)的术语。执行此装箱操作会在堆上分配内存(垃圾回收器最终将需要回收该内存)。取消装箱是此过程的逆过程,它采用引用类型并将其转换为值类型。
强制转换采用一种类型(例如System.Object)并将其视为另一种类型(例如System.String)。
当您在C#中装箱某些东西时,会将其转换为另一种类型。不同之处在于,当创建新的引用类型时,它会分配额外的内存。
底线:装箱是一种特殊的类型转换,它将值类型转换为引用类型,这需要分配新的引用类型。
IComparable<int> i = 5
导致拳击。其次,boxing
不是唯一需要内存分配的演员表。用户定义的强制转换也可以这样做。第三,正如Jason所指出的,堆是实现细节。重要的是通过引用类型语义而不是在其分配位置来处理值类型。
装箱意味着将值类型变量(即整数)转换为引用类型。使用类型转换,取消装箱是相反的操作。简而言之,在.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
这样做的好处是类型系统的统一,允许将值类型视为引用类型。本文对装箱/拆箱有更深入的了解。