从MSDN我读到装箱/拆箱用于将值类型视为对象。但是当我读到关于ArrayList的内容时,它会读到它也会装箱。所以我很困惑,因为ArrayList将值和引用类型保存为对象。 另外,在术语方面,以下内容不是拆箱,只是铸造?
ArrayList a=new ArrayList();
a.Add(someClass);
someClass x=(someClass)a[0];
答案 0 :(得分:8)
ArrayList
对值类型执行装箱,但不执行引用类型。或者更确切地说,ArrayList
本身不会进行拳击 - 编译器会这样做。例如:
ArrayList list = new ArrayList();
list.Add(5);
实际上是
ArrayList list = new ArrayList();
object boxed = 5; // Perform boxing from value type type
list.Add(boxed);
您的示例确实只是强制转换 - 引用转换,而不是取消装箱转换。参考类型值不需要加框以存储在ArrayList
中 - 它已经是参考。
同样,拳击一般都是如此,而不是ArrayList
特有的。拳击只是一种使用值类型值的方法,其中你真的想要一个引用...引用必须是一个对象,所以CLR创建一个对象来包装值类型值,并且返回对该包装器的引用(存储该值的“box”)。
答案 1 :(得分:2)
装箱/拆箱是语言和运行时的一项功能,而不是ArrayList
的功能。简而言之,it's the conversion of a value type from/to the Object
type以及ArrayList
收到Object
后,您传递的任何值类型都会自动加上box
IL指令。
更具体地说,装箱/拆箱涉及创建或检查新对象,以及将值类型的数据从堆栈复制到堆(反之亦然)。这是相当昂贵的,如果可能的话你想避免它。
在引用类型的情况下,通常不生成装箱代码;此外,任何对引用类型进行操作的unbox
指令都会被忽略。
答案 2 :(得分:0)
我认为将值类型视为类类型系统之外是有用的,但是将每个值类型视为具有从ValueType派生的不可见的对应引用类型(其又从Object派生),其实质上表现为类与Foo相同的成员,但支持在实际值类型中扩展强制转换。
如果将值类型传递给需要Object派生的代码,则会将其强制转换为相应的不可见引用类型;如果将该引用类型的对象分配给值类型的变量,则将对其进行强制转换。
顺便说一句,如果我有我的druthers,会有一些方法指定应该使用除默认的投射方法之外的其他东西,但是不存在这样的特征。