You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:42:02