委托与事件

来源:互联网 发布:诺基亚java软件 编辑:程序博客网 时间:2024/06/15 22:12

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。


Net中的委托从功能上讲和c语言或者c++中的方法指针类似,可以像调用方法一样调用委托完成某个功能,或返回某类结果。但是.Net毕竟是更高级的语言,委托Delegate也更高级了,委托是一种数据接口,它包含调用目标和调用方法的指针;而在.Net中定义的委托都继承自MulticastDelegate即多播委托,所谓的多播委托是指可以包含多个调用方法的委托。


委托的定义:
如下C#代码定义委托
public delegate void DoSomething(int times);
委托的定义包含5个部分
1) public表示委托的可访问性
2) delegate关键字表示要定义一个委托
3) void表示委托定义方法的返回值
4) DoSomething是委托的名字
5) (int times) 是委托方法的参数列表,此处的参数列表可以包括ref参数,也可以有out参数,同样也可以有parms可变数量参数;需要注意如果委托中有多个调用方法,使用out参数时只能返回委托最后执行成功的一个委托方法的计算值



Delegate

delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名 (signature),并且它只能持有与它的签名相匹配的方法的引用。它所实现的功能与C/C++中的函数指针十分相似。它允许你传递一个类A的方法m 给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数指针不具备的优点。首先,函数指针只能指向静态函 数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而 且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是 说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。
实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate:

 

1.  声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。

2.  创建delegate对象,并将你想要传递的函数作为参数传入。

3.  在要实现异步调用的地方,通过上一步创建的对象来调用方法。


public class MyDelegateTest{        // 步骤1,声明delegate对象        public delegate void MyDelegate(string name);        // 这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型        public static void MyDelegateFunc(string name)        {               Console.WriteLine("Hello, {0}", name);        }        public static void Main()        {               // 步骤2,创建delegate对象               MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);               // 步骤3,调用delegate               md("sam1111");        }}


事件(event)
C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:
public delegate void MyEventHandler(object sender, MyEventArgs e);
其 中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从 System.EventArgs类派生。当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数。
就是这么简单,结合delegate的实现,我们可以将自定义事件的实现归结为以下几步:

 

1.           定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。
2.           定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。
3.           定义事件处理方法,它应当与delegate对象具有相同的参数和返回值类型。
4.           用event关键字定义事件对象,它同时也是一个delegate对象。
5.           用+=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。
6.           在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是OnEventName。
7.           在适当的地方调用事件触发方法触发事件。

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 = Console.ReadLine();            if(s == "a")            {                   et.RaiseEvent();            }            else            {                   Console.WriteLine("Error");            }     }}

输出结果如下,

 

Please input ‘a’: a

My event is ok!




0 0