【发布时间】:2011-05-10 07:08:16
【问题描述】:
由于引用值作为数据存储在堆中;任何引用值的类型信息都存放在哪里?
如果有几个 Artist 类的实例;当它们存储在堆中时,.Net 如何将这些内存块标记为 Artist 类型?
谢谢!
【问题讨论】:
标签: c# .net vb.net memory reference
由于引用值作为数据存储在堆中;任何引用值的类型信息都存放在哪里?
如果有几个 Artist 类的实例;当它们存储在堆中时,.Net 如何将这些内存块标记为 Artist 类型?
谢谢!
【问题讨论】:
标签: c# .net vb.net memory reference
void M()
{
Artist a = new Artist();
}
当方法被调用时,一个新的栈帧被展开,CLR在方法的第一条语句被执行之前有一些准备代码,就像一个prolegomenon。在此期间,CLR 加载方法中使用的所有类型。在这个例子中,Artist 的类型将被加载到堆中。但也有可能该类型已经存在,因为在调用 M() 之前使用了该类型。然后我们来到第一个表达式,new 语句,它调用类的构造函数。如果您查看它生成的 CIL,您会看到类似 newobjblabla 的内容。这里堆上的一块内存被分配用于存储实例。块的大小取决于类的细节,因为块需要保存实例的所有数据。通常块由以下组成:
Type pointer + Sync root + Instance data
类型指针指向它在堆上的类型(加载在prolegomenon中)。同步根是用于锁定和同步的记录。实例数据存储实例的成员数据。
【讨论】:
CLR 将一些信息与对象实例中的数据一起存储。其中之一是指向对象类型的指针。
【讨论】:
就在第一次使用类之前,dotnet 运行时在堆上创建一个对象,该对象存储有关要使用的类的所有信息。这包括静态字段、指向类可用方法的方法表、类型对象指针(稍后会详细介绍)和同步块(用于锁定对象)。
所有对象都有一个类型对象指针,它指向一个存储类信息的对象。
因此,例如,如果您有一个 Person 对象,它将有一个类型对象指针,该指针指向堆上的一个对象,该对象存储有关人员的所有信息。这个 person 的 Type 对象还有一个指向 System.Type 对象的类型对象指针,因为它的类型是 System.Type(它是一个存储对象类型信息的对象)。
当然,System.Type 作为堆上的对象也有一个类型对象指针,它指向关于它是什么类型的信息。正如您可能已经猜到的那样 - 它指向自身,因为 System.Type 对象是 System.Type 对象。
当您在对象上调用 GetType() 时,它只返回存储在特定对象类型对象指针中的地址。
【讨论】: