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

子类调用基类实现的接口事件触发异常问题咨询

问题分析与解决方案

为啥会抛出异常?

咱们先明确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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:59:27