如何将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
相关产品推荐
相关产品推荐

