深入解析c#编程中的事件_c#应用

2008-02-23 05:44:31来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

  一个事件是个使对象或类能够提供公告的成员。用户能够通过提供事件句柄来为事件添加可执行代码。事件使用事件声明来声明:

  一个事件声明既能够是个事件域声明也能够是事件属性声明。在每种情况中,声明都能够由属性集合, new 修饰符, 四个访问修饰符的有效组合 和一个静态修饰符组成。

  一个事件声明的类型必须是个代表类型, 而那个代表类型必须至少同事件本身相同可访问。

  一个事件域声明和一个声明了一个或多个代表类型域的域声明相应。在一个事件域声明中不允许有readonly 修饰符。

  一个事件属性声明和声明了一个代表类型属性的属性声明相应。除了同时包含get访问符和set访问符的事件属性声明,成员名称和访问符声明对于那些属性声明来说都是相同的,并且不允许包含virtual、 override和abstract 修饰符。

  在包含一个事件成员声明的类或结构的程式文字中,事件成员和代表类型的私有域或属性相关,而这个成员能够用于任何允许使用域或属性的上下文中。

  假如一个类或结构的程式文字外面包含一个事件成员声明,这个事件成员就只能被作为 = 和 -= 操作符 (§的右手操作数使用。这些操作符被用来为事件成员附加或去掉事件句柄,而这个事件成员的访问操作符控制操作在其中被执行的上下文。

  由于 = 和 -= 是唯一能够在声明了事件成员的类型外的事件上使用的操作,外部代码能够为一个事件添加或去掉句柄,但是不能通过任何其他途径获得或修改基本事件域或事件属性的数值。

  在例子中

public delegate void EventHandler(object sender, Event e);
public class Button: Control
{
 public event EventHandler Click;
 protected void OnClick(Event e) {
  if (Click != null) Click(this, e);
 }
 public void Reset() {
  Click = null;
 }
}

  对使用Button类中的Click事件域没有限制。作为演示的例子,这个域能够在代表调用表达式中被检验、修改和使用。类Button中的OnClick方法"引起"Click事件。引起一个事件的概念和调用由事件成员表示的代表正好相同-因此,对于引起事件没有特别的语言构造。注意代表的调用是通过检查确保代表是非空后才进行的。

  在类Button的声明外面,成员Click只能被用在 = 和 -= 操作符右手边,如下

b.Click = new EventHandler(...);

  他把一个代表附加到事件Click的调用列表中,并且

b.Click -= new EventHandler(...);

  他把一个代表从Click事件的调用列表中删除。

  在一个形式为x = y 或 x -= y的操作中,当x是个事件成员而引用在包含x的声明的类型外面发生时,操作的结果就是void(在赋值后和x的数值相反)。这个规则禁止外部代码直接检查事件成员的基本代表。
下面的例子介绍了事件句柄如何附加到上面的类Button的实例中:

public class LoginDialog: Form
{
 Button OkButton;
 Button CancelButton;
 public LoginDialog() {
  OkButton = new Button(...);
  OkButton.Click = new EventHandler(OkButtonClick);
  CancelButton = new Button(...);
  CancelButton.Click = new EventHandler(CancelButtonClick);
 }
 void OkButtonClick(object sender, Event e) {
  // Handle OkButton.Click event
 }
 void CancelButtonClick(object sender, Event e) {
  // Handle CancelButton.Click event
 }
}

  这里,构造函数LoginDialog创建了两个Button实例,并且把事件句柄附加到事件Click中。

  事件成员是典型域,就像上面的Button例子中所示。在每个事件消耗一个域存储的情况是不可接受的,一个类能够声明事件属性来替代事件域,并且使用私有机制来存储基本的代表。(设想在某种情况下,大多数事件都是未处理的,每个事件使用一个域就不能被接受。使用属性而不是域的能力允许研发人员在空间和时间上面取得一个折中方案。)

  在例子中

class Control: Component
{
 // Unique keys for events
 static readonly object mouseDownEventKey = new object();
 static readonly object mouseUpEventKey = new object();
 // Return event handler associated with key
 protected Delegate GetEventHandler(object key) {...}
 // Set event handler associated with key
 protected void SetEventHandler(object key, Delegate handler) {...}
 // MouseDown event property
 public event MouseEventHandler MouseDown {
  get {
   return (MouseEventHandler)GetEventHandler(mouseDownEventKey);
  }
  set {
   SetEventHandler(mouseDownEventKey, value);
  }
 }
 // MouseUp event property
 public event MouseEventHandler MouseUp {
  get {
   return (MouseEventHandler)GetEventHandler(mouseUpEventKey);
  }
  set {
   SetEventHandler(mouseUpEventKey, value);
  }
}
}

  类Control为事件提供了一种内部存储机制。方法SetEventHandler用一个key来和代表数值相关,而方法GetEventHandler返回和key相关的当前代表。大概基本的存储机制是按照把空代表类型和key相关不会有消耗而设计的,因此无句柄的事件不占用存储空间。
  实例变量初始化函数

  当一个构造函数没有构造初始化函数或一个形式为base(...)的构造函数初始化函数,构造函数就就隐含的执行被类中声明的实例域的变量初始化函数指定的初始化。这和赋值序列相关,这些赋值在直接基类构造函数的隐式调用前,在构造函数的入口被直接执行。变量初始化函数按照他们在类声明中出现的文字顺序执行。

  构造函数执行

  能够把一个实例变量初始化函数和一个构造函数初始化函数,看作是自动插在构造函数主体中的第一条语句前。例子

using System.Collections;
class A
{
 int x = 1, y = -1, count;
 public A() {

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: c#中的非安全编程_c#应用

下一篇: 解读c#中的正则表达式_c#应用