c# 委托与事件

委托
是C#中的一种引用类型,类似于C/C++中的函数指针(一个c++函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针)。
委托是一个特殊的类,类的实例是对象,但委托的实例没有专门的名称。
声明一个委托:
public delegate void my_delegate_1(Object sender, EventArgs e);
产生委托的实例:
public delegate int my_delegate_2(int x,int y);
class math_class 
{
   public int sub(int x, int y)
   {
     return(x+y);
   }
 }
my_delegate_2 del_example_1 = new my_delegate_2(math_class.sub);
接下来可以直接使用del_example_1调用sub方法了:
del_example_1(23,7)

事件

委托的最基本的一个用处就是用于事件处理。
在类中声明一个事件成员一般采用如下的语法形式:
public event 委托名 事件名
事件的定义用关键字event声明,不过声明事件之前必须存在一个多路广播委托:
  public delegate void my_delegate_3(int x,int y);
//返回值为void的委托自动成为多路广播委托.
声明事件:  
  public event  my_delegate_3 my_event_1;
如在Control类中声明了一个Click事件成员,其语法如下:
public event EventHandler Click;

Eventhandler是一个delegate
类型,其在类库中声明如下:
public delegate void EventHandler(object sender,EventArgs e);
这样,所有形如:
void 函娄名(object 参数名,EventArgs 参数名);
的函数都可以作为Control类的Click事件响应方法了。
其中第一个参数指明了触发该事件的对象即sender,由于引发事件的对象不可预知的,因此我们把其声明成为object类型,所有的对象都适用。
第二个参数(e)包含了在事件处理函数中可以被运用的一些数据,各种类型的事件中可能不同,这要根据类中事件成员的说明决定。
如下面所定义的一个事件响应方法:
private void button1_Click(object sender, System.EventArgs e);
由于是通过delegate来处理事件,因此,可通过 += 使一个事件具有多个响应方法;与此同时,还可以使一个方法作为多个事件的响应方法。

实例:
创建两个类,A类将提供事件的处理函数,并在步骤3中创建委托对象同时将事件处理函数包含在其中,事件处理函数的参数形式必须和委托对象的参数形式相一致然后,A类将委托对象传递给B类。当B类中的事件被触发后, A类中的事件处理函数就相应的被调用了。下面是示例代码:

using System;
//步骤1:声明委托
public delegate void MyHandler1(object sender,MyEventArgs e);
public delegate void MyHandler2(object sender,MyEventArgs e);

//步骤2:创建事件处理函数的方法
class A{
public const string m_id="Class A";
public void OnHandler1(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler1 and MyEventArgs is {0}",
e.m_id);
}
public void OnHandler2(object sender,MyEventArgs e){
Console.WriteLine("I am in OnHandler2 and MyEventArgs is {0}",
e.m_id);
}

//步骤3:创建委托对象,并事件处理函数包含在其中同时设置好将要触发事件的对象
public A(B b){
MyHandler1 d1=new MyHandler1(OnHandler1);
MyHandler2 d2=new MyHandler2(OnHandler2);
b.Event1 +=d1;
b.Event2 +=d2;
}
}

//步骤4:通过委托对象(也就是触发事件)来调用被包含的方法
class B{
public event MyHandler1 Event1;
public event MyHandler2 Event2;
public void FireEvent1(MyEventArgs e){
if(Event1 != null){
Event1(this,e);
}
}
public void FireEvent2(MyEventArgs e){
if(Event2 != null){
Event2(this,e);
}
}
}
public class MyEventArgs EventArgs{
public string m_id;
}
public class Driver{
public static void Main(){
B b= new B();
A a= new A(b);
MyEventArgs e1=new MyEventArgs();
MyEventArgs e2=new MyEventArgs();
e1.m_id ="Event args for event 1";
e2.m_id ="Event args for event 2";
b.FireEvent1(e1);
b.FireEvent2(e2);
}
}

C#中的GUI的事件处理函数:

  完成GUI下的事件处理函数的基本方法和上面介绍的并没有什么多大区别,下面我们就通过上面的方法来完成一个简单的实例程序。该实例程序的主类 MyForm类是从Form类继承过来的。通过观察整段代码和相关的注解,你可以发现我们并没有给它声明委托对象并通过event关键字来引用该委托对象,那是因为GUI控件早就帮我们做好了该项工作,其委托对象是System.EventHandler。然而,我们还是要为各个控件定义方法(也就是事件的处理函数)并将它们包含在创建好的委托对象(System.EventHandler)中。那样,在用户和程序进行交互的时候,相应的事件处理函数就会被触发。具体代码如下:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

public class MyForm Form{
private Button m_nameButton;
private Button m_clearButton;
private Label m_nameLabel;

private Container m_components = null;

public MyForm(){
initializeComponents();
}
private void initializeComponents(){
m_nameLabel=new Label();
m_nameButton = new Button();
m_clearButton = new Button();

SuspendLayout();

m_nameLabel.Location=new Point(16,16);
m_nameLabel.Text="Click NAME button, please";
m_nameLabel.Size=new Size(300,23);

m_nameButton.Location=new Point(16,120);
m_nameButton.Size=new Size(176, 23);
m_nameButton.Text="NAME";
//创建委托对象,包含方法并将委托对象赋给按钮的Click事件
m_nameButton.Click += new System.EventHandler(NameButtonClicked);

m_clearButton.Location=new Point(16,152);
m_clearButton.Size=new Size(176,23);
m_clearButton.Text="CLEAR";
//创建委托对象,包含方法并将委托对象赋给按钮的Click事件
m_clearButton.Click += new System.EventHandler(ClearButtonClicked);

this.ClientSize = new Size(292, 271);
this.Controls.AddRange(new Control[] {m_nameLabel,
m_nameButton,
m_clearButton});
this.ResumeLayout(false);
}
//定义方法(事件的处理函数),其参数形式必须和委托对象的一致
private void NameButtonClicked(object sender, EventArgs e){
m_nameLabel.Text=
"My name is john, please click CLEAR button to clear it";
}
private void ClearButtonClicked(object sender,EventArgs e){
m_nameLabel.Text="Click NAME button, please";
}
public static void Main(){
Application.Run(new MyForm());
}
}




URL:http://blog.chinaunix.net/u/13205/showart_70291.html
原文地址:https://www.cnblogs.com/yiki/p/684990.html