子类调用基类实现的接口事件触发异常问题咨询
问题分析与解决方案
为啥会抛出异常?
咱们先明确C#里事件的核心规则:事件在定义它的类外部,只能做订阅(+=)或取消订阅(-=)操作,绝对不能直接触发。
你写的BoomObject类里定义了OnBoom事件,它的底层委托字段是类的私有成员——哪怕子类Grenade继承了BoomObject,也无权直接访问这个私有委托来调用触发(也就是OnBoom()这行代码)。这就是你看到异常的根本原因,完整的异常信息应该是The event 'BoomObject.OnBoom' can only appear on the left hand side of += or -=。
正确的实现方式
要让子类能触发基类的事件,基类应该提供一个受保护的虚拟方法来封装事件触发逻辑,子类可以通过调用或重写这个方法来间接触发事件。修改后的代码如下:
delegate void Default(); public interface IBoom { event Default OnBoom; } public class BoomObject : IBoom { public event Default OnBoom; // 提供受保护的虚拟方法用于触发事件 protected virtual void OnBoomTriggered() { OnBoom?.Invoke(); // 用空条件运算符替代null判断,更简洁 } public virtual void Start () { } } public class Grenade : BoomObject { public override void Start () { // 调用基类的触发方法 OnBoomTriggered(); } }
这种做法是不是良好编程实践?
直接在子类触发基类事件绝对不是好的实践,原因有两点:
- 破坏封装性:事件的触发逻辑应该由定义它的类来掌控,子类直接绕过基类触发事件,会让基类失去对事件触发时机、前置条件的控制能力(比如基类可能需要在触发前检查对象状态是否合法)。
- 降低可维护性:如果后续基类要在事件触发前后添加统一逻辑(比如日志记录、参数校验),直接触发事件的子类代码会全部失效,需要逐一修改。
而通过基类提供的受保护方法来触发事件,既符合面向对象的封装原则,又能让基类保留对事件的控制权,同时子类也能灵活地在合适的时机触发事件,是业内通用的最佳实践。
内容的提问来源于stack exchange,提问作者Honey
相关产品推荐
相关产品推荐

