拳击/拆箱 - 仅限值类型? Ref.types - 铸造?

时间:2011-01-17 07:44:21

标签: c# casting boxing unboxing

从MSDN我读到装箱/拆箱用于将类型视为对象。但是当我读到关于ArrayList的内容时,它会读到它也会装箱。所以我很困惑,因为ArrayList将值和引用类型保存为对象。 另外,在术语方面,以下内容不是拆箱,只是铸造?

ArrayList a=new ArrayList();
a.Add(someClass);

someClass x=(someClass)a[0];

3 个答案:

答案 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,会有一些方法指定应该使用除默认的投射方法之外的其他东西,但是不存在这样的特征。