拳击/拆箱和types转换有什么区别?
拳击/拆箱和types转换有什么区别?
通常,这些术语似乎可以互换使用。
拳击是指将非空值types转换为引用types或将值types转换为它实现的某个接口(比如说int
为IComparable<int>
)。 此外,基础值types转换为可空types也是一种装箱转换。 (注意:这个主题的大部分讨论将忽略后两种types的转换。)
例如,
int i = 5; object o = i;
将i
转换为一个object
types的实例。
拆箱是指从object
或ValueType
实例到非空值types的显式转换,即将接口types转换为非空值types(例如, IComparable<int>
为int
)。 此外,可空types转换为基础types也是拆箱转换。 (注意:这个主题的大部分讨论将忽略后两种types的转换。)
例如,
object o = (int)5; int i = (int)o;
将o
的整数转换为int
types的实例。
types转换是expression式到给定types的显式转换。 从而
(type) expression
显式地将expression
转换为typestype
的对象。
拳击和拆箱是types转换的一个子集。 拳击是将值types作为引用types(在实践中涉及将该值types的内容(从堆栈)复制到堆并将引用返回给该对象)的行为。 这允许在需要兼容的引用types的地方传递值types。 它还允许对值types执行虚拟方法调用和引用types的其他function。 拆箱与此操作相反(从盒装对象中取回值types)。
types转换是用于从特定types的variables到另一types的任何types的转换的术语。 这是一个更广泛的概念。
几分钟前, 我回答了一个涉及这个区别的相关问题 。 总而言之,我对由C#转换运算符生成的不同types的IL指令进行了分类:
- 拳击(
box
IL指令)和拆箱(unbox
IL指令) - 通过inhertiance层次结构(如C ++中的
dynamic_cast<Type>
,使用castclass
IL指令进行validation) - 在原始types之间进行转换(如C ++中的
static_cast<Type>
,对于原始types之间的不同types的转换,有很多IL指令) - 调用用户定义的转换运算符(在IL级别,它们只是方法调用适当的
op_XXX
方法)。
拳击是将值types(int,double,float,guid等)转换为引用types(System.Object,System.String等)的术语。 做这个装箱操作在堆上分配内存(垃圾收集器最终需要回收)。 拆箱就是这个过程的反面,取一个引用types并把它变成一个值types。
铸造是采取一种types(比如System.Object),并将其视为另一种types(比如System.String)。
当你用C#打开某些东西的时候,你正在把它转换成另一种types。 不同之处在于它会在创build新的引用types时分配额外的内存 。
底线:装箱是一种特殊types的转换,将值types转换为引用types,这需要分配一个新的引用types。
装箱/拆箱和types转换是两种不同的操作,但是它们使用相同的语法。
他们只能在谈话的人不知道真正发生的事情时互换使用。
拳击将一个值types存储在堆上的对象,拆箱正在读取对象的值。 您只能将值作为确切types取消装箱。
当您将基本types转换为另一种基本types(如从int
到long
)或者当您更改引用的types(如从List<int>
到IEnumerable<int>
)时,Casting就是这种情况。
装箱意味着将一个值typesvariables(即一个整数)转换为一个引用types。 拆箱是相反的,使用types铸造。 在.NET世界中,一切都来自于“对象”types。
例如(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
从这个出发是types系统的统一,允许价值types被视为参考types。 这篇文章有一个更深入的看拳击/拆箱。