使用 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 来做,则可以解决这个问

 

题,原因很容易理解,我就不多废话了。

posted on 2007-12-26 18:43  优哉@游哉  阅读(410)  评论(0编辑  收藏  举报

导航