3

MSDN 链接中引用 ValueType 类

如果值类型必须表现得像对象,则在堆上分配一个使值类型看起来像引用对象的包装器,并将值类型的值复制到其中。包装器被标记以便系统知道它包含一个值类型。

这意味着当我编写像“integerVariable.ToString();”这样的代码时 创建的包装对象允许使用此方法以及 System.Object 的所有其他方法。

这种理解正确吗?

这些对象与“常规”对象有何不同?

此类对象的垃圾收集是否不同?如果是,如何?

提前致谢。

4

2 回答 2

6

包装器是一个“盒子”;重新收集盒子的垃圾 - 就抓取收集器而言,没有区别。一个盒子的收集规则和处理与任何其他对象完全相同。

但是,如果值类型覆盖了方法(例如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 
}

Note that ToString() doesn't involve a box, but GetType() does at L_0007 (since it isn't (can't be) overridden)

于 2009-01-06T10:25:02.940 回答
1

是的,这个理解是正确的。

这些对象与 CLR 中的“常规”对象没有什么不同。

由于这些对象(也称为“盒子”,因为它们包装了值类型)就像任何其他对象一样,垃圾收集器也是一样的。

于 2009-01-06T10:17:25.967 回答