2

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

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

someClass x=(someClass)a[0];
4

3 回答 3

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 创建一个对象来包装值类型值,并返回对该包装器的引用(存储值的“盒子”)。

于 2011-01-17T07:46:47.767 回答
2

装箱/拆箱是语言和运行时的一个特性,而不是ArrayList. 粗略地说,它是值类型从/到Object类型的转换,并且由于ArrayList接受了Objects,因此您传递的任何值类型都将自动与boxIL 指令一起装箱。

更具体地说,装箱/拆箱涉及创建或检查新对象,并将值类型的数据从堆栈复制到堆(反之亦然)。它相当昂贵,如果可能的话,你想避免它。

在引用类型的情况下,一般不会生成装箱码;此外,任何unbox对引用类型进行操作的指令都将被简单地忽略。

于 2011-01-17T07:47:01.437 回答
0

我发现将值类型视为在类类型系统之外很有用,但将每个值类型视为具有从 ValueType 派生的不可见的相应引用类型(它又从 Object 派生),它本质上表现为具有相同成员的类作为 Foo,但支持扩大与实值类型之间的转换。

如果将值类型传递给期望 Object 派生的代码,它将被强制转换为适当的不可见引用类型;如果将该引用类型的对象分配给值类型的变量,它将被强制转换回。

顺便说一句,如果我有我的 druthers,将会有某种方式来指定应该使用默认铸造方法以外的东西,但不存在这样的功能。

于 2011-01-26T17:26:17.110 回答