结构体实现INotifyPropertyChanged报错:构造函数需完全赋值PropertyChanged
解决结构体实现INotifyPropertyChanged时"PropertyChanged必须在构造函数中完全赋值"的错误
这个问题我之前也踩过坑,本质是结构体作为值类型的初始化规则和引用类型(类)不一样导致的:CLR要求值类型的所有字段(包括事件背后的委托字段)必须在构造函数中完成初始化,而类的字段会默认被初始化为null,所以类里不会触发这个错误。下面给你几个可行的解决办法:
方法1:在构造函数中显式初始化事件字段
直接在结构体的构造函数里给PropertyChanged事件赋值为null(委托类型的合法初始值),就能满足CLR的初始化要求:
public struct LogCurve : INotifyPropertyChanged { // 添加构造函数初始化事件 public LogCurve() { PropertyChanged = null; } private void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; public void Notify() { OnPropertyChanged(string.Empty); } }
注意:如果你的项目用的是C# 6之前的版本,自定义无参构造函数可能会有问题,这时可以改用带参数的构造函数,同样在里面初始化
PropertyChanged。
方法2:使用字段初始化器(C# 6+推荐)
从C# 6开始,结构体支持字段初始化器,你可以直接在事件声明时赋值,省去写构造函数的麻烦:
public struct LogCurve : INotifyPropertyChanged { private void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; handler?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 直接在声明时初始化事件 public event PropertyChangedEventHandler PropertyChanged = null; public void Notify() { OnPropertyChanged(string.Empty); } }
额外建议:谨慎用结构体实现INotifyPropertyChanged
最后提个醒:结构体是值类型,当你把它用于数据绑定场景时,值类型的赋值会创建副本,很可能导致PropertyChanged通知无法正确传递到UI层。如果没有必须用结构体的特殊理由,更推荐把LogCurve改成类,这样不仅能避免这个初始化问题,还能避免值类型带来的绑定坑。
内容的提问来源于stack exchange,提问作者paparazzo
相关产品推荐
相关产品推荐

