Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对象如何存储在内存中?_C#_.net_Memory Management - Fatal编程技术网

C# 对象如何存储在内存中?

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

我试图理解对象是如何使用.NET Framework存储在内存中的

给定以下
人员
类别:

public class Person
{
    public string name { get; set; }

    public int age { get; set; }
}
我相信
Person
类型的初始变量在内存中具有以下结构:

问题:

  • 首先,他们在我的理解上是否有任何重大/明显的缺陷?(我几乎可以肯定有,因为以我所描述的方式处理对象似乎很有效;尤其是
    name
    指针指向字符串成员的char集合的方式)

  • 其次,对于类的值类型成员(即
    Age
    ),它们是存储在对象本身中(因此与对象在同一内存地址中),还是分配给它们自己的地址,然后对象指向它?(如我的图表所示)

  • 与上述问题类似,但对于引用类型成员,对象是否持有指向指针的指针?(即在我的图表中引用char集合的名称指针)

  • 最后,如果我的
    Person
    类的成员是字段而不是属性,这会有区别吗

更新:根据Sweeper&Tim的回答更新了图表,我相信现在是正确的


注意:指针更改为引用,因为这是托管代码。

我将从最容易回答的问题开始:

如果我的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方法。因此,图形中的“名称”和“年龄”实际上是字段,它们将具有不同的名称。

感谢您的解释。我已经根据你和蒂姆的答案添加了一个更新的图表,我相信现在是正确的?