从MSDN Link for ValueType Class
引用如果值类型的行为必须像对象一样,则在堆上分配使值类型看起来像引用对象的包装器,并将值类型的值复制到其中。标记包装器,以便系统知道它包含值类型。
这意味着我的代码就像“integerVariable.ToString();”创建的包装器对象允许使用此方法,类似于System.Object的所有其他方法。
这种理解是否正确?
这些对象与“常规”对象有何不同?
此类对象的垃圾收集是否不同?如果是,怎么样?
提前致谢。
答案 0 :(得分:6)
包装是一个“盒子”;垃圾收集盒 - 就垃圾收集器而言,存在 no 差异。收集的盒子具有与任何其他物体完全相同的规则和处理。
但是,如果值类型覆盖方法(例如ToString()
),则无需将其设置为调用方法。因此,值类型应该(作为例程)覆盖尽可能多的object
方法;-p
您可以看到IL(通过反射器)的差异 - 因此对于C#:
static int GetInteger() {return 123;}
static string TestToString() {
int i = GetInteger(); // to prove no cheating
return i.ToString();
}
static Type TestGetType() {
int i = GetInteger(); // to prove no cheating
return i.GetType();
}
我们有IL:
.method private hidebysig static string TestToString() cil managed
{
.maxstack 1
.locals init (
[0] int32 i)
L_0000: call int32 Program::GetInteger()
L_0005: stloc.0
L_0006: ldloca.s i
L_0008: call instance string [mscorlib]System.Int32::ToString()
L_000d: ret
}
.method private hidebysig static class [mscorlib]System.Type TestGetType() cil managed
{
.maxstack 1
.locals init (
[0] int32 i)
L_0000: call int32 Program::GetInteger()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: box int32
L_000c: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
L_0011: ret
}
请注意,ToString()
不涉及框,但GetType()
执行L_0007
(因为它不会(不能)覆盖)
答案 1 :(得分:1)
是的,理解是正确的。
这些对象与CLR中的“常规”对象没有区别。
由于这些对象(也称为'box'因为它们包装值类型)就像任何其他对象一样,垃圾收集器也是一样的。