从 MSDN 我读到装箱/拆箱是将值类型视为对象。但是当我读到 ArrayList 时,它读到它也可以装箱。所以我很困惑,因为 ArrayList 将值和引用类型作为对象保存。此外,以下不是在术语方面的拆箱,它只是铸造?
ArrayList a=new ArrayList();
a.Add(someClass);
someClass x=(someClass)a[0];
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 创建一个对象来包装值类型值,并返回对该包装器的引用(存储值的“盒子”)。
装箱/拆箱是语言和运行时的一个特性,而不是ArrayList
. 粗略地说,它是值类型从/到Object
类型的转换,并且由于ArrayList
接受了Object
s,因此您传递的任何值类型都将自动与box
IL 指令一起装箱。
更具体地说,装箱/拆箱涉及创建或检查新对象,并将值类型的数据从堆栈复制到堆(反之亦然)。它相当昂贵,如果可能的话,你想避免它。
在引用类型的情况下,一般不会生成装箱码;此外,任何unbox
对引用类型进行操作的指令都将被简单地忽略。
我发现将值类型视为在类类型系统之外很有用,但将每个值类型视为具有从 ValueType 派生的不可见的相应引用类型(它又从 Object 派生),它本质上表现为具有相同成员的类作为 Foo,但支持扩大与实值类型之间的转换。
如果将值类型传递给期望 Object 派生的代码,它将被强制转换为适当的不可见引用类型;如果将该引用类型的对象分配给值类型的变量,它将被强制转换回。
顺便说一句,如果我有我的 druthers,将会有某种方式来指定应该使用默认铸造方法以外的东西,但不存在这样的功能。