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

如何将Action委托作为类属性传递?遇只读赋值错误求解

解决方法:通过转发事件暴露委托

你的问题核心是直接暴露只读属性无法支持委托的订阅操作,因为+=本质是对委托实例的赋值,而只读属性不允许修改。下面是两种可行的解决方案,优先推荐更安全的事件转发方式:

方案一:使用事件转发(推荐)

将Controller的DataChanged定义为事件,在add和remove访问器中直接操作Data类的ValueChanged委托,实现订阅逻辑的转发:

public class Data {
    private float value;

    // 建议把Data的委托也改成事件,增强封装性
    public event Action<float> ValueChanged;

    public void UpdateValue(float delta){
        value += delta;
        // 修复笔误:ValueChange → ValueChanged
        ValueChanged?.Invoke(delta);
    }
}

public class Controller {
    private Data data; // 确保已初始化

    public event Action<float> DataChanged {
        add { data.ValueChanged += value; }
        remove { data.ValueChanged -= value; }
    }
}

public class SomeOtherClass {
    private Controller controller;

    public void Init(Controller controller){
        this.controller = controller;
        // 现在可以正常订阅
        controller.DataChanged += PrintDelta;
    }

    public void PrintDelta(float delta){  
        Console.WriteLine(delta);
    }
}

这种方式的优势:

  • 符合C#封装规范,外部只能执行+=/-=操作,无法直接赋值或调用委托,避免意外修改。
  • 完全复用Data类的委托逻辑,无需额外维护状态。

方案二:使用可读写属性(不推荐)

如果一定要用属性实现,可通过get/set直接操作Data的委托字段,但这种方式会暴露委托的全部权限(外部可直接清空、调用委托),存在安全风险:

public class Controller {
    private Data data;

    public Action<float> DataChanged {
        get => data.ValueChanged;
        set => data.ValueChanged = value;
    }
}

为什么原写法失败?

你用的表达式主体属性public Action<float> DataChanged => data.ValueChanged;本质是只读属性(仅包含get访问器),而委托的+=操作需要修改属性的值(创建新的委托实例并赋值),因此会触发"无法赋值给只读属性"的错误。

内容的提问来源于stack exchange,提问作者Sayon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:35:11