事件与委托有别, delegate 与 Delegate 相异
我们都知道事件是特殊的委托,特殊在哪儿?
我只发现了一点,就是委托类型在初始化时可以用“=”,而事件只能是“+="。这使得事件处理程序只能一个个的往上挂,然后用”-=“一个个的注销,从而避免了委托的”=“一下子只赋为一个方法或赋为 null 而遭清空。这有用吗?有用。比如你开发组件的时候,某个业务对象的事件被触发,你想先在组件内部处理一下,处理完了再往外传,让组件调用方处理,这时你就得用 event 声明;如果只是声明为 delegate,则可能组件调用方一个“=”赋值,你的方法就没机会执行了。由此可见,如果可能会多次委托处理,应该声明为 event;只处理一次,delegate 就够了。
实际上 delegate 也可以用“+=”赋值,此时效果跟 event 一样。但谁敢保证调用方不会来个“=”呢!
delegate 之所以也能“+=”赋值,是因为用 delegate 声明的委托实际是 System.MulticastDelegate 类型,叫多路广播委托,天生拥有多路广播的能力。
注意,delegate 开头是小写的 d,如果换成大写开头的 Delegate,那差别可就大了,简直是孙子和爷爷的区别。为什么说是孙子和爷爷呢?因为 delegate 仅仅是 C# 的关键字,表示一个继承自 System.MulticastDelegate 的具体委托类,而 Delegate 却是 System.MulticastDelegate 的父类,这还不是孙子和爷爷吗。另外,Delegate 和 System.MulticastDelegate 都是抽象类,只有编译器才可以从此类派生。也就是说,除了用 delegate 这种形式,我们不能显式地从这两个类派生。
关于 delegate 和 Delegate,我以前一直以为是一样的,就像 string 之于 String,bool 之于 Boolean,仅仅是个方便书写的别名。这次发现它们的区别,是在看王翔的新书《设计模式——基于C#的工程化实现》时。王翔说“delegate 声明的 Delegate 类型其实本身继承自 System.MulticastDelegate ”,我认为他说反了,寻思着给人家发个邮件指出一个 bug,没想到是我自己没弄清楚。
最后感叹一下,王翔跟我同年同级,他海大物理系毕业,也算半路出家。同样毕业七年,人家都出书了,我还得努力啊。