C#中如何使嵌套对象B.obj始终引用变量a的当前对象?
问题描述
定义两个类:
class A { public int n { get; set; } }
class B { public A obj { get; set; } }
主程序中创建对象并赋值:
A a = new A() { n = 1 }; B b = new B() { obj = a };
此时b.obj.n的值为1,但当重新给a赋值新对象后:
a = new A() { n = 5 };
b.obj.n仍然是1,而非预期的5。需要实现让b.obj始终引用变量a的当前对象。
原因分析
你混淆了引用类型变量和对象实例的关系:
- 变量
a是一个引用,它存储的是对象在内存中的地址。 - 执行
b.obj = a时,是把a当时指向的对象地址复制给了b.obj,两者此时指向同一个对象。 - 但执行
a = new A() { n =5 }时,a的地址被更新为新对象的地址,而b.obj仍然保存着原来的旧对象地址,自然不会跟着变化。
解决方案
要让b能始终获取a的当前引用,有几种常用方式:
1. 使用包装类包裹引用
定义一个能持有A引用的包装类,让B持有这个包装类的实例,而不是直接持有A:
class RefWrapper<T> { public T Value { get; set; } } class B { public RefWrapper<A> ObjWrapper { get; set; } }
使用方式:
RefWrapper<A> wrapper = new RefWrapper<A> { Value = new A { n = 1 } }; A a = wrapper.Value; B b = new B { ObjWrapper = wrapper }; // 重新赋值a时,通过包装类更新 wrapper.Value = new A { n =5 }; a = wrapper.Value; // 此时b.ObjWrapper.Value.n 就是5
2. 使用委托延迟获取当前引用
让B存储一个返回A的委托,每次需要获取时调用委托拿到a的当前值:
class B { public Func<A> GetCurrentA { get; set; } }
使用方式:
A a = new A { n =1 }; B b = new B { GetCurrentA = () => a }; a = new A { n=5 }; // 调用委托获取当前a的引用 int currentN = b.GetCurrentA().n; // 结果为5
3. 使用ref关键字(仅限特定场景)
如果是在方法内的局部变量,可以用ref来传递引用,但这种方式不适合长期持有引用(比如类的字段),因为ref不能直接作为类的成员存储(C# 7.2+有ref struct但限制较多),仅适合临时传递场景。
注意:第一种包装类的方式是最通用、最容易维护的方案,适合大多数场景;第二种委托方式适合需要动态获取当前值的场景。
内容的提问来源于stack exchange,提问作者Cleo Ku
相关产品推荐
相关产品推荐

