在.NET中,对象引用的具体类型是什么?

时间:2011-02-02 00:08:08

标签: .net reference clr

即。存储在堆栈中的值类型数据结构的名称是什么,它引用堆上的对象?

即。一个对象引用是System.What(如果有的话)?

我知道这不是pointer,不是吗?

我知道它“像”一个指针。

我知道它“归垃圾收集者所有”。

我超自然地相信当你实例化一个对象(即一个引用类型)时,IL会给CLR指令以在内存中分配“堆栈引用/堆值对”(例如

...
      .locals init ([0] int32 i1,
               [1] object o1,
               [2] int64 l1)
      IL_0000:  nop
      IL_0001:  ldc.i4.4
      IL_0002:  stloc.0
      IL_0003:  newobj     instance void [mscorlib]System.Object::.ctor()
      IL_0008:  stloc.1
      IL_0009:  ldloc.0
      IL_000a:  box        [mscorlib]System.Int32
...

) ,并且在语言或IL级别上无法访问实际引用(复制/分配给新引用或操作引用对象除外),并且CLR / CLI创建和管理对象引用的分配,并且CLR注入OBJECTREF DWORD值进入堆栈(或类似)。

请让我直截了当,并为所有图书作者和谷歌搜索结束这一点。

谢谢!

2 个答案:

答案 0 :(得分:4)

在堆栈上创建的值类型没有对堆上任何对象的引用 - 堆上没有相应的对象。这只会在列入值类型时创建 - 在这种情况下,这两者之间仍然没有任何关系。

这就是为什么当您更改盒装引用类型的值时,原始变量保持不变。无论什么时候装箱,都会创建一个新对象。

这是一个简单的方法:

    private void TestBoxing()
    {
        int i = 52;
        object io = i;
        io = "something else";

    }

这是生成的IL代码:

.method private hidebysig instance void  TestBoxing() cil managed
{
  // Code size       18 (0x12)
  .maxstack  1
  .locals init ([0] int32 i,
           [1] object io)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   52
  IL_0003:  stloc.0
  IL_0004:  ldloc.0
  IL_0005:  box        [mscorlib]System.Int32
  IL_000a:  stloc.1
  IL_000b:  ldstr      "something else"
  IL_0010:  stloc.1
  IL_0011:  ret
} // end of method Program::TestBoxing

正如您所看到的,这个.locals init ([0] int32 i, [1] object io)只是启动局部变量,一个int和一个对象。


(更新)

  

我在问具体是什么   堆栈上的引用类型   它指的是堆上的对象

它是普通对象引用,类似于所有对象引用,它引用内存中具有4字节类型指针和4字节同步块的点,然后休息与对象一样多的空间要求,在我们的例子中,int需要4个字节,所以12个字节。


(UPDATE2)

嗯,我认为它没有名称,它是 CLR的内部指针(32位或64位,具体取决于运行时),它在CLR之外没有用,并且没有公开。如您所知,并且它由GC管理,因为在垃圾收集后对象在堆上移动后,值将会发生变化。

答案 1 :(得分:2)

它是一个指针,大小与本机字长相关(即x86上的32位指针,x64上的64位指针)。在我认为你的意思中,它没有CTS暴露的“类型”。