随笔 - 54  文章 - 2 评论 - 79 阅读 - 69803
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

Effective C# Item 35: Prefer Overrides to Event Handlers

      许多.net类库中的类都提供了两种不同的处理事件句柄的方法。既可以为其添加事件,也可以重写其基类的事件抽象方法。为什么要为同一件事提供两种不同的方法呢?这是为了对应不同的情况。在实现派生类的时候,更好的选择是重写基类中的抽象方法。

      假设我们现在正在编写一个windows应用程序,这个程序需要对鼠标按键按下的事件做出响应。在自定义的Form类中,我们可以选择重写OnMouseDown()事件:

    public class MyForm : Form
    
{
        
protected override void OnMouseDown(MouseEventArgs e)
        
{
            
try
            
{
                HandleMouseDown(e);
            }

            
catch
            
{
                
//error
            }

            
base.OnMouseDown(e);
        }

    }

      或者添加事件句柄:

    public class MyForm : Form
    
{
        
public MyForm()
        
{
            
this.MouseDown += new MouseEventHandler(MyForm_MouseDown);
        }

 
        
void MyForm_MouseDown(object sender, MouseEventArgs e)
        
{
            
try
            
{
                HandleMouseDown(e);
            }

            
catch
            
{
                
//error
            }

        }

    }

      这里推荐使用第一种方法。一旦事件句柄抛出异常,不会再有其他的事件句柄被调用。这避免了一些错误代码继续被调用而引发的问题。通过重写受保护的虚方法,我们的句柄可以第一个被调用。基类中虚函数负责其他相关句柄的调用。这意味着如果需要调用那些事件句柄(一般来说是需要的),就要调用基类的虚函数。在有些特殊情况下我们需要替换基类的默认行为,可能不需要调用任何原有的事件句柄。虽然我们不能保证所有的事件句柄都被执行,因为其可能会抛出异常,但是我们可以保证派生类的行为是正确的。

      使用override比添加事件句柄高效的多。在Item 22中展示了System.Windows.Forms.Control类是如何存储句柄时间并将其对应到每一个事件的。这种事件机制由于要检查事件句柄将造成更多的消耗。事件句柄列表中的每个方法都需要执行。相比重写虚方法,通过事件处理会消耗更多的时间。

      如果这还不足以说服你,咱们可以再回头看一下开始时候的代码。哪一种更清晰?重写虚方法只需要维护一个函数就可以达到检查和修改的目的。而事件机制需要两个维护点:事件句柄函数和事件绑定代码。其中任何一点都可能造成整体功能上的失败。一个函数显然要简单些。

      这些就是使用重写和不是事件句柄的理由。但是.net设计者之所以会提供事件也是有其理由的。他们不会做无用的工作。这种重写是针对派生类的。除此之外的情况我们必须使用事件机制。例如我们经常需要为Form添加一个按钮的点击事件。这个事件由按钮引发,在form中处理。当然我们可以搞一个自定义按钮,然后在里面重写点击的虚方法,但这太繁琐了,为了处理一个事件,需要创建一个自定义的按钮类,完全是在给自己找麻烦。而使用事件机制就非常的简单。这也是.net framework设计者在设计事件机制的一个理由。

      另外一个理由是事件的绑定是在运行期进行的。我们可以更加灵活的处理事件,在运行时为其绑定不同的事件。假设我们正在编写一个绘图程序,点击鼠标可能是画线的开始,也可能是选取某个对象。我们可以在使用者切换模式的时候来切换这些事件。而且,我们可以为同一个事件添加多个事件句柄。

      当我们创建派生类时,应当使用重写虚函数的方法来处理事件。这样便于维护也更加高效。其他情况则应该使用事件句柄。

      译自   Effective C#:50 Specific Ways to Improve Your C#                      Bill Wagner著

      回到目录

 

posted @ 2007-06-16 19:25 aiya 阅读(1405) 评论(1) 推荐(0) 编辑
摘要: Effective C# Item 40: Match Your Collection to Your Needs 根据需要选用恰当的集合 阅读全文
posted @ 2007-06-08 14:22 aiya 阅读(1477) 评论(0) 推荐(0) 编辑
摘要: 简单介绍跟踪侦听器及其使用 阅读全文
posted @ 2007-06-01 16:26 aiya 阅读(1233) 评论(3) 推荐(0) 编辑
摘要: Effective C# Item 31: Prefer Small, Simple Functions 推荐使用小且简单的函数 阅读全文
posted @ 2007-05-27 21:03 aiya 阅读(1356) 评论(4) 推荐(0) 编辑
摘要: Effective C# Item 30: Prefer CLS-Compliant Assemblies 让程序集符合CLS(公共语言规范) 阅读全文
posted @ 2007-05-21 14:49 aiya 阅读(1335) 评论(0) 推荐(0) 编辑
摘要: Chapter 4 Create Binary Components 创建二进制组件 阅读全文
posted @ 2007-04-25 19:35 aiya 阅读(808) 评论(1) 推荐(0) 编辑
摘要: Effective C# Item29: Use the new Modifier Only When Base Class Updates Mandate it 只在更新基类的情况下使用new修饰符 阅读全文
posted @ 2007-04-22 11:40 aiya 阅读(856) 评论(0) 推荐(0) 编辑
摘要: Effective C# Item 28: Avoid Conversion Operators 尽量避免转换操作 阅读全文
posted @ 2007-04-14 14:57 aiya 阅读(976) 评论(2) 推荐(0) 编辑
摘要: Effective C# Item 27: Avoid ICloneable 避免使用ICloneable接口 阅读全文
posted @ 2007-04-07 16:10 aiya 阅读(882) 评论(1) 推荐(0) 编辑
摘要: Effective C# Item 26: Implement Ordering Relations with IComparable and IComparer 通过IComparable和IComparer接口来实现排序关系 阅读全文
posted @ 2007-03-26 11:17 aiya 阅读(903) 评论(1) 推荐(1) 编辑
点击右上角即可分享
微信分享提示