C# 事件

事件的模型:

C#使用了委托模型来实现事件。例如:应用程序有两个不同作用的按钮,只要写一个通用按钮类(事件源),再写不同的事件处理程序,然后通过委托联系起来就可以了。这样就节省了一个按钮类。

委托为什么能把事件源跟事件处理程序连接起来呢?这是因为委托提供了对指定了返回类型和参数列表的方法的一般引用。方法做什么对于委托来说并不重要,而这种特性正好可以用来解决事件的问题。我们可以把委托定义为生成事件类的一个成员,用来把事件的处理方法与事件关联起来,这样当事件发生时,调用委托,就可以调用事件处理程序。

static、virtual、override、abstract作为事件的修饰符时,同一时刻只能出现一个。如果是使用了abstract修饰符的事件,必须省略事件访问说明,否则编译器会提示错误。事件的声明中可以包含事件访问说明,也可以省略事件访问说明,省略时编译器会自动提供一个访问器。

事件委托的一般形式:delegate-modifiers delegate void delegate-name(object source,EventArgs e)

事件委托可用的访问修饰符与一般的委托一样,但是其返回值类型总是void,它们的参数列表总是两个参数。第一个参数代表事件源,第二个参数是EventArgs类的一个实例,或其派生类的一个实例,包含事件另外的信息。

.NET框架定义了大量的事件委托,内建的委托都派生于System.Delegate类,如下所示:

public delegate void ColumnClickEventHandler(object source,ColumnClickEventArgs args);

public delegate void DragHandler(object source,DragEventArgs);

public delegate void MouseEventHandler(object source,MouseEventArgs args);

public delegate void KeyEventHandler(object source,KeyEventArgs args);

用户可以定义自己的事件委托,但必须按照前面说过的语法定义。如果想定义一个委托响应一个名为MyObject对象的变化,可以这样定义:

public delegate void MyObjectEventHander(object source,MyobjectEventHandler args);

事件处理程序:

事件处理程序是事件委托所调用的方法。因为跟事件委托联系在一起,所以事件处理程序和事件委托有相同的参数列表和返回值类型。事件的预定就是把事件处理程序和事件关联起来,事件的撤销就是把事件处理程序和事件断开来。事件的预定通过为事件加上左操作符“+=”来实现。这样,只要事件被触发,方法就会被调用。事件的撤销采用左操作符“-=”来实现。

事件的触发:就是把事件委托的一个实例定义为类的成员,让类能够触发事件。生成事件的类应该定义什么时候生成事件的代码,还应该定义生成提供事件的EventArgs对象的代码。要触发事件,只需要调用事件委托实例就可以。要调用委托实例,输入委托实例的名称,后跟要传递给事件处理方法的参数就可以了。当事件生成时,有关事件的信息被传递给任何已向事件源注册的事件处理程序。

事件存储器:

大多数情况下,事件的声明都省略了事件存储器,可是当 每个事件的存储开销时,就可以在类中声明事件的存储。声明事件存储是按私有成员的规则来存放事件句柄列表。存储器的声明有两种情况:添加存储器和删除存储器声明。


当查看代码时,就会发现在后台创建了一个私有的委托字段,和添加并删除委托的两个方法。这是因为类中的每个事件都声明一个字段,又因为委托时引用类,这就意味着对于类的每个实例,都将在堆中为类中声明的每个事件分配内存空间。这就会造成资源的极大浪费。解决的方法就是定义自己存储添加和删除方法。


你可能感兴趣的:(C# 事件)