转自:http://www.hubwiz.com/

  事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些出现,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。事件是用于进程间通信。

  事件在类中声明且生成,且通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件。这被称为 发布器(publisher) 类。其他接受该事件的类被称为 订阅器(subscriber) 类。事件使用 发布-订阅(publisher-subscriber) 模型。


发布器(publisher) 是一个包含事件和委托定义的对象。事件和委托之间的联系也定义在这个对象中。发布器(publisher)类的对象调用这个事件,并通知其他的对象。


订阅器(subscriber) 是一个接受事件并提供事件处理程序的对象。在发布器(publisher)类中的委托调用订阅器(subscriber)类中的方法(事件处理程序)。


事件声明


  事件和方法一样具有签名,签名包括名称和参数列表。事件的签名通过委托类型来定义,然后向类中添加事件需要使用 event 关键字,并提供委托类型和事件名称。例如:


public delegate void TestEventDelegate(object sender, System.EventArgs e);

public class EventSource

{

   public event TestEventDelegate TestEvent; //基于上面的委托

   private void RaiseTestEvent() { /* ... */ }

}



  事件可标记为 public、private、protected、internal 或 protected internal。这些访问修饰符定义类的用户访问事件的方式。


自定义事件


  C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:


    public delegate void MyEventHandler(object sender, MyEventArgs e);


  其中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从System.EventArgs类派生。

  结合delegate的实现,我们可以将自定义事件的实现归结为以下几步:

  1. 定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。

  2. 定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。

  3. 定义"事件处理方法,它应当与delegate对象具有相同的参数和返回值类型"。

  4. 用event关键字定义事件对象,它同时也是一个delegate对象。

  5. +=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。

  6. 在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是OnEventName。

  7. 在适当的地方调用事件触发方法触发事件。

  以下代码的功能是输入'a'触发事件。


using System;

public class EventTest

{

   // 步骤1,定义delegate对象

   public delegate void MyEventHandler(object sender, System.EventArgs e);

   // 步骤2(定义事件参数类)省略

   public class MyEventCls

   {

       // 步骤3,定义事件处理方法,它与delegate对象具有相同的参数和返回值类型

       public void MyEventFunc(object sender, System.EventArgs e)

       {

           Console.WriteLine("My event is ok!");

       }

   }

   // 步骤4,用event关键字定义事件对象

   private event MyEventHandler myevent;

   private MyEventCls myecls;

   public EventTest()

   {

       myecls = new MyEventCls();

       // 步骤5,用+=操作符将事件添加到队列中

       this.myevent += new MyEventHandler(myecls.MyEventFunc);

   }

   // 步骤6,以调用delegate的方式写事件触发函数

   protected void OnMyEvent(System.EventArgs e)

   {

       if (myevent != null)

           myevent(this, e);

   }

   public void RaiseEvent()

   {

       EventArgs e = new EventArgs();

       // 步骤7,触发事件

       OnMyEvent(e);

   }

   public static void Main()

   {

       EventTest et = new EventTest();

       Console.Write("Please input ''a'':");

       string s = "a";

       Console.WriteLine(s);

       if (s == "a")

       {

           et.RaiseEvent();

       }

       else

       {

           Console.WriteLine("Error");

       }

   }

}


匿名方法


  委托是用于引用与其具有相同标签的方法。换句话说,使用委托对象调用可由委托引用的方法。

  匿名方法(Anonymous methods) 提供了一种传递代码块作为委托参数的技术。匿名方法是没有名称只有主体的方法,不需要指定返回类型,它是从方法主体内的 return 语句推断的。

  匿名方法是通过使用 delegate 关键字创建委托实例来声明的。例如:


delegate void NumberChanger(int n);

NumberChanger nc = delegate(int x)

{

   Console.WriteLine("Anonymous Method: {0}", x);

};


  委托可以通过匿名方法调用,也可以通过命名方法调用,即,通过向委托对象传递方法参数。如上面的可以调用为:


nc(1);


  下面通过实例来了解一下匿名方法。


using System;

namespace test

{

   delegate void Printer(string s); //声明委托

   class TestClass

   {

       static void Main()

       {

           // 初始化匿名方法

           Printer p = delegate(string j)

           {

               System.Console.WriteLine(j+" anonymous method");

           };

           p("The delegate using the method is called:");  //调用匿名方法

           p = new Printer(TestClass.DoWork); //实例化委托

           p("using the named method is called: ");//调用DoWork方法

       }

       static void DoWork(string k)

       {

           System.Console.WriteLine(k + "dowork");

       }

   }

}