C# 对象如何存储在内存中?
我试图理解对象是如何使用.NET Framework存储在内存中的 给定以下C# 对象如何存储在内存中?,c#,.net,memory-management,C#,.net,Memory Management,我试图理解对象是如何使用.NET Framework存储在内存中的 给定以下人员类别: public class Person { public string name { get; set; } public int age { get; set; } } 我相信Person类型的初始变量在内存中具有以下结构: 问题: 首先,他们在我的理解上是否有任何重大/明显的缺陷?(我几乎可以肯定有,因为以我所描述的方式处理对象似乎很有效;尤其是name指针指向字符串成员的char
人员
类别:
public class Person
{
public string name { get; set; }
public int age { get; set; }
}
我相信Person
类型的初始变量在内存中具有以下结构:
问题:
- 首先,他们在我的理解上是否有任何重大/明显的缺陷?(我几乎可以肯定有,因为以我所描述的方式处理对象似乎很有效;尤其是
指针指向字符串成员的char集合的方式)name
- 其次,对于类的值类型成员(即
),它们是存储在对象本身中(因此与对象在同一内存地址中),还是分配给它们自己的地址,然后对象指向它?(如我的图表所示)Age
- 与上述问题类似,但对于引用类型成员,对象是否持有指向指针的指针?(即在我的图表中引用char集合的名称指针)
- 最后,如果我的
类的成员是字段而不是属性,这会有区别吗Person
注意:指针更改为引用,因为这是托管代码。我将从最容易回答的问题开始: 如果我的Person类的成员是字段而不是属性,会有区别吗 不。代码中的属性只是语法上的糖分。编译代码时,这些带有
{get;set;}
的属性将转换为字段,带有getter和setter
我的理解中是否存在任何重大/明显的缺陷
对。当我回答以下问题时,我会提到它们
其次,对于类的值类型成员(即年龄),它们是存储在对象本身中(因此与对象在同一内存地址中),还是分配给它们自己的地址,然后对象指向它?(如我的图表所示)
你的第一句话是正确的。值类型存储在对象中。Person
对象中没有指向int
的指针。换句话说,您的图表是错误的
但是对于引用类型成员,对象是否持有指向指针的指针?(即在我的图表中引用char集合的名称指针)
在本例中,
char[]
是您已经注意到的引用类型。但它实际上包含了一堆char
s,它们是值类型。不,字符存储在char数组中,就像Age
存储在Person
中一样。另一方面,如果这是一个字符串[]
,则会有一个指向数组的指针,其中包含指向字符串对象的指针。这也意味着您的关系图是错误的。在.net世界中,指针指向非托管内存,对象引用指向托管对象。垃圾收集器可以随时移动对象,因此指向它们的指针将在没有警告的情况下被销毁。概念是相同的,但有一点不同,因为在不安全的C#代码中确实可以有指针。如果抓取指向某个对象的指针,并且该对象移动,则指针指向任意内存空间。但是,将保留对象引用
关于年龄的问题。它存储在对象本身中,在结构中占用32位,而不是指向int32的引用/指针
对于引用类型成员,它持有一个引用,这在概念上与指针的概念相同,并且占用64位空间(或者32位,取决于体系结构),但与我上面提到的有所不同
最后,匿名属性实际上是在创建隐藏字段,以及设置和重新设置这些字段的自动编写代码。存储是一样的,但通过属性而不是直接通过字段访问存储的成本非常低。存在一些错误。您的
int
成员错误,它是值类型。因此没有指针,它包含在Person对象的存储中,占用4个字节。名称对象引用看起来也不太正确,它指向一个字符串对象。字符串中的字符包括在字符串的存储中,这与int
was非常相似。换句话说,字符串对象存储的大小是可变的,与存储字符所需的大小一样大
因此,访问Person对象的成员只需要取消引用两个指针,这样效率更高
是的,Person类型的变量只存储指针。GC在压缩堆时更新它
属性在运行时不存在,它是编译器提供的抽象。最典型的情况是,编译器将为它分配一个字段,除非您自己提供getter和setter方法。因此,图形中的“名称”和“年龄”实际上是字段,它们将具有不同的名称。感谢您的解释。我已经根据你和蒂姆的答案添加了一个更新的图表,我相信现在是正确的?