C#类中嵌套属性更新失效问题求助
问题根源:
Meta属性的Getter每次返回新实例,导致修改丢失 哥们儿,你这个问题的核心坑点我一眼就看出来了——DataObject.Meta的getter每次调用都会创建并返回一个全新的Metadata对象,而不是返回一个绑定到DataObject内部_data的持久化实例。
咱们拆解一下你执行dataObj.Meta.Prop0 = 8;时到底发生了什么:
- 调用
dataObj.Meta的getter:它会从_data里复制前2个字节,新建一个Metadata实例 - 修改这个临时
Metadata的Prop0:这只会修改这个临时对象自己内部的_metadata数组,和DataObject的_data半毛钱关系都没有 - 这个临时对象用完就被GC回收了:你根本没触发
Meta的setter,自然不会把修改同步到_data里
而Property1能正常工作,是因为它的setter直接接收你传入的数组,调用UpdateData修改_data,全程没有中间临时对象搞事情。
两种修复方案,按需选择
方案1:让Metadata直接操作原始_data数组(推荐)
这个方案最直观,让Metadata不再复制子数组,而是直接持有对DataObject._data的引用和偏移量,修改属性时直接修改原始数组的对应位置。
修改后的Metadata类:
public class Metadata { private byte[] _originalData; private int _offset; // 不再复制数组,直接绑定原始数据和偏移位置 public Metadata(byte[] originalData, int offset) { _originalData = originalData; _offset = offset; } // 保留GetData方法,返回子数组的副本(如果需要的话) public byte[] GetData() { byte[] arr = new byte[2]; Array.ConstrainedCopy(_originalData, _offset, arr, 0, 2); return arr; } public byte Prop0 { get { return _originalData[_offset]; } set { _originalData[_offset] = value; } // 直接修改原始数组 } public byte Prop1 { get { return _originalData[_offset + 1]; } set { _originalData[_offset + 1] = value; } // 直接修改原始数组 } }
修改DataObject的Meta属性:
public class DataObject { private byte[] _data; public DataObject(byte[] objectData) { _data = objectData; } public byte[] GetData() { return _data; } // 每次返回的Metadata直接绑定原始_data public Metadata Meta { get { return new Metadata(_data, 0); } set { UpdateData(0, value.GetData()); } } public byte[] Property1 { get { return GetSubarray(2, 5); } set { UpdateData(2, value); } } private void UpdateData(int start, byte[] data) { Array.ConstrainedCopy(data, 0, _data, start, data.Length); } private byte[] GetSubarray(int start, int length) { byte[] arr = new byte[length]; Array.ConstrainedCopy(_data, start, arr, 0, length); return arr; } }
方案2:手动触发Meta的Setter(临时 workaround)
如果你不想修改类结构,可以手动把修改后的Metadata实例赋值回Meta属性,触发setter同步到_data:
// 替换原来的dataObj.Meta.Prop0 = 8; var tempMeta = dataObj.Meta; tempMeta.Prop0 = 8; dataObj.Meta = tempMeta; // 触发setter,更新_data
但这个方案容易忘,代码也不优雅,只适合临时调试用。
修复后的验证
现在再跑你的测试代码:
DataObject dataObj = new DataObject(new byte[7]{1,1,1,1,1,1,1}); dataObj.Meta.Prop0 = 8; dataObj.Property1 = new byte[5]{8,8,8,8,8}; CollectionAssert.AreEqual(new byte[7]{8,1,8,8,8,8,8}, dataObj.GetData()); // ✅ 通过 Assert.AreEqual(8, dataObj.Meta.Prop0); // ✅ 通过 Assert.AreEqual(new byte[5]{8,8,8,8,8}, dataObj.Property1); // ✅ 依然正常
内容的提问来源于stack exchange,提问作者isswf
相关产品推荐
相关产品推荐

