.NET 9中接口默认实现触发事件为何引发编译错误?
接口默认方法中触发事件为何被禁止?
我正在.NET 9、C# 13中使用**default interface methods(接口默认方法)**特性。考虑以下接口:
public interface ICustomNotifyPropertyChanged: INotifyPropertyChanged { public void OnPropertyChanged (string propertyName); // Compiler Error: [CS0079]. //public void OnPropertyChanged (string propertyName) // => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); protected bool SetField<T> (ref T field, T value, [CallerMemberName] string propertyName = "") { if (EqualityComparer<T>.Default.Equals(field, value)) { return (false); } field = value; this.OnPropertyChanged(propertyName); return (true); } }
尝试为OnPropertyChanged添加默认实现时出现如下错误:
CS0079: The event 'ICustomNotifyPropertyChanged.PropertyChanged' can only appear on the left hand side of += or -=.
我并非询问该用法是否恰当,而是想了解为何不允许在接口默认实现中触发事件,若允许会产生哪些不良情况?
原因分析
1. 接口事件仅为契约,无存储能力
接口中定义的事件本质是契约声明,只要求实现类提供订阅/取消订阅的逻辑,接口自身并不负责存储事件的委托列表。而触发事件需要访问具体的委托实例(调用Invoke),但接口无法获取实现类内部的委托存储——不同实现类的事件存储方式可能完全不同:有的用自动实现事件的隐式字段,有的用自定义的显式add/remove逻辑,接口没有统一的访问路径。
2. 剥夺实现类的自主性
事件触发逻辑本属于实现类的责任范畴,实现类可能需要在触发前做校验、日志,或者处理线程安全等自定义逻辑。如果接口默认方法强制接管事件触发,会直接剥夺实现类对事件触发时机、条件的控制权,违背封装原则。
3. 引发空引用与排查困难
若允许接口默认方法触发事件,当实现类未正确初始化事件委托(比如显式实现的add/remove逻辑有问题),调用Invoke时会直接抛出NullReferenceException。而且这种错误会被默认方法隐藏,很难区分是实现类的问题还是接口默认方法的问题,增加排查难度。
4. 遵循语言设计一致性
C#始终规定:接口中的事件只能用于+=/-=操作,不能直接访问底层委托。默认方法作为接口的一部分,必须遵守这一规则,否则会打破语言设计的一致性,增加语法和逻辑复杂度。
内容的提问来源于stack exchange,提问作者Raheel Khan
相关产品推荐
相关产品推荐

