示例代码中Connection属性是引用还是副本?其内存行为如何?
关于
Another.Connection属性的引用/副本问题及内存行为 嘿,这个问题问到点子上了,我给你拆解明白:
首先要明确一个核心点:C#里的class是引用类型,struct是值类型,你的Something是类,所以它的实例是存储在托管堆上的,而用来指向它的变量/属性,存储的是这个堆上实例的内存地址(也就是“引用”)。
1. Connection属性是引用还是副本?
Another类里的Connection属性,存储的是指向Something实例的引用的副本——注意,不是Something实例的副本,而是引用本身的副本。换句话说,它和你传入构造函数的那个Something变量,指向的是堆上同一个Something实例。
2. 具体的内存行为是怎样的?
咱们用代码例子来直观理解:
// 1. 创建一个Something实例,它被存在托管堆上 var mySomething = new Something { Id = 1, Name = "初始名称" }; // 2. 创建Another实例,把mySomething传入构造函数 var myAnother = new Another(2, "测试Another", mySomething);
这时候内存里的情况是:
mySomething作为局部变量会存在栈上,存储着堆上Something实例的内存地址;- 调用
Another构造函数时,参数connection会拿到这个内存地址的副本; - 构造函数把这个副本赋值给
myAnother.Connection属性,所以myAnother.Connection现在也存储着同一个堆上实例的地址。
这意味着:
- 如果你修改
mySomething.Name = "更新后的名称",那么myAnother.Connection.Name也会变成“更新后的名称”——因为它们指向同一个对象; - 反过来,修改
myAnother.Connection.Id = 99,mySomething.Id也会变成99,道理完全一样。
常见误区澄清
别把“引用类型”和“引用传递”搞混:C#默认参数传递是值传递,对于引用类型来说,传递的是“引用的副本”,而不是对象本身。所以构造函数里的赋值操作,只是把这个引用副本存到属性里,并没有复制整个Something实例。
如果Something是struct(值类型),那情况就完全不同了——赋值时会创建整个实例的副本,修改其中一个不会影响另一个,但这里它是类,所以是引用类型的引用副本传递。
内容的提问来源于stack exchange,提问作者Guapo
相关产品推荐
相关产品推荐

