C#中引用类型所持引用类型的内存存储位置问询
C#内存分配分析(针对你的代码)
首先是你的代码:
public class Wallet { private int _money; public Wallet(int money) { _money = money; } } public class Person { private string _name; private Wallet _wallet; public Person(string name) { _wallet = new Wallet(0); _name = name; } } class TestClass { static void Main(string[] args) { var person = new Person("Toto"); } }
你的理解验证
- 第1点正确:
person是Main方法里的局部引用变量,存储在栈上,指向堆上的Person实例。 - 第2点补充:Person的成员
_name和_wallet是堆上Person实例的一部分,它们本身是引用类型的引用(而非实例),这两个引用存储在堆上,分别指向对应的字符串实例和Wallet实例。 - 第3点正确:
_money是Wallet类的值类型成员,Wallet实例在堆上,所以_money嵌入在堆上的Wallet实例中,存储在堆上。
你的疑惑解答
你关于“_wallet的引用存储在栈上”的理解是错误的。_wallet是Person类的成员字段,属于堆上Person实例的一部分,所以这个引用本身存在堆上,它指向堆上的Wallet实例。
完整内存分配流程梳理
- 执行
new Person("Toto")时,堆上创建Person实例,实例包含_name(string引用)和_wallet(Wallet引用)两个字段,均存储在堆上。 - 执行
_wallet = new Wallet(0)时,堆上创建Wallet实例,_money作为值类型嵌入该实例中;随后将Wallet实例的地址赋值给Person实例里的_wallet引用(堆上的引用)。 - 字符串"Toto"是引用类型实例,存储在堆上,Person实例的
_name引用指向该字符串实例。 - Main方法里的
person局部引用变量存储在栈上,指向堆上的Person实例。
一句话总结
栈上仅存在Main方法的person引用变量;堆上包含Person实例(含两个引用字段)、Wallet实例(含_money值)、字符串"Toto"实例。
内容的提问来源于stack exchange,提问作者Milan
相关产品推荐
相关产品推荐

