求知若饥,虚心若愚
使用多拨委托编码Publish-Subscribe模式
- 调用委托前记得判空,c#6.0后可使用空条件操作符,即?.Invoke()
- c#6.0前可采用如下写法
1
2
3
4
5
6
7
8
9
10···
// 先保存局部变量可避免此时判空后有线程将委托清空
// 是由于-=作用于委托时会返回新实例,所以不会影响局部保存的这个
// 但是要注意的是,在多线程程序中,订阅者应确保这种情况下的健壮性,随时做好调用一个"过时"订阅者的准备。
Action<float> localOnChange = OnTemperatureChange;
if(localOnChange != null)
{
localOnChange(value);
}
··· - 多拨委托可使用+|-|+=|-=来对委托操作,实际内部是使用了System.Delegate.Combine()和System.Delegate.Remove()
- 由于多拨委托实际是维护一个委托链表,如果调用过程中发生异常,后续订阅者不会收到通知。此时可以通过委托类的GetInvocationList()方法获得订阅者列表,手动遍历并配合try/catch处理异常。
使用事件改进
- 事件
- 委托问题:
- 不经意使用’='操作符覆盖了委托,清空了原先委托链
- 外部类也能轻易调用委托而不是真正有事件发生,有点狼来了感觉(除非把该委托封装,但那样新增订阅者需要专门的函数,实际上事件也是这么封装的)
- 容易遗忘判空处理(事件可以默认空委托而不是null)