使用 override 还是用 event?
一个类重写基类的虚方法是面向对象惯用的手法,而.Net 引入事件机制后,使得我
们在重写一些方法是往往放心不下,特别是BCL 里面以On 打头的虚方法,在重写时,往往
要调用base.On..., 否则会出问题,那是先调用base.On... 还是实现了自己的方法
后再调用呢, 也比较难确定,于是不得不看BCL 基类的实现。以Control 类为例
Control 类OnPaint 的实现:
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void OnPaint(PaintEventArgs e) {
PaintEventHandler handler = (PaintEventHandler) base.Events[EventPaint];
if (handler != null) {
handler(this, e);
}
}
可以看出,很多virtual 的方法只是简单地调用一个委托,以触发事件。由此可以
得知,如果我们重写了一个方法,而没有调用base 的方法,可能导致事件不会被触发。
所以MSDN 告诉我们要调用base.On... 方法。
然后就是调用顺序的问题,一般来讲,为了防止基类的调用覆盖父类的代码,应该先
调用base, 比如要写一个自定义控件MyButton,继承自Button 于是重写OnPaint, 先调用
base.OnPaint, 再写自定义代码,以防止自定义Paint的内容看不到。也就是说,只能先调
用base,现在我们开始使用我们的自定义控件了,一个需求来了,要在Button
上画一个三角形,怎么办?很简单,使用事件,button.Paint += MyButtonOnPaint; 很快
你就会发现,我们的代码根本不起作用,无论你怎么写这段绘制代码,就是看不到三角形。
其实原因很简单,我们的事件代码做完后,MyButton.OnPaint 才执行的,所以我们在事件
里面画的东西被MyButton 里面的OnPaint 里面画的东西给盖住了。
实际上, BCL 里面的控件override OnPaint 的时候大都是先OnPaint 再调用base 的,因为
他们保证了base.OnPaint 只是触发事件,不会有绘制代码。这就不会有问题。
如果在MyButton 里面使用事件this.Paint += MyButtonOnPaint 来做,则可以解决这个问
题,原因很容易理解,我就不多废话了。