一步一步学习C#(五 委托与事件)
1.事件原理:
在说明事件的原理之前,我们先来做一个例子,如下:
1、启动VS,建立一个winform应用程序,在form窗口中,我们建立一个按钮,当点击这个按钮时,弹出消息"you clicked me!"。
2、关于winform我们在以后会详细讲解。
3、我们双击按钮后,在button1的click事件中的代码如下: private void button1_Click(object sender, EventArgs e)
{ MessageBox.Show("you clicked me!"); } 这是一个完整的私有方法,参数为object sender和EventArgs e。
解释: Object sender与 EventArgs e
(1)第一个参数sender是object基类,它表示了button1类本身,可以经过显式转换为button1类. (Button)sender
(2)EventArgs是包含事件数据的类的基类,用于传递事件的细节,EventArgs是所有其它事件类的基类。
把方法和事件联系起来:
(1) 我们通过程序界面看到,代码如下: this.button1.Click += new System.EventHandler(this.button1_Click);
(2)this表示类本身(即form)而button1是它的一个控件,Click 是button预定义的一个标准事件
(3)通过 += 将 一个System.EventHandler(this.button1_Click)的方法赋给了click事件。
System.EventHandler
(1)System.EventHandler 就是一个系统预定义的委托。
(2)该委托将事件与事件处理程序连接。
(3)委托是一个定义签名的类型,即方法的返回值类型和参数列表类型。
(4)系统的委托声明如下 public delegate void EventHandler( object sender , EventArgs e ) 它定义了一个函数(方法)签名的方式。
(5)private void button1_Click(object sender, EventArgs e) 满足此签名方式: 一、没有返回值 二、传入参数
2.委托
(1)委托是一个类.
(2)它包含对方法的引用
(3)帮助决定在运行时调用哪个方法
(4)步骤 –
1. 定义委托
2. 实例化委托
3. 使用委托
(5)如上面的new System.EventHandler(this.button1_Click);
1 1-->委托实例化:
2 //定义委托
3 public delegate int CallFun(int a, int b);
4 class MathsOperations
5 {
6 public int MulFun(int a, int b)
7 {
8 return a * b;
9 }
10 public int DivFun(int a, int b)
11 {
12 return a / b;
13 }
14 }
15 //实例化委托1(乘法)
16 CallFun DelegateObj1=new CallFun(MathsOprations.MulFun);
17 //实例化委托2(除法)
18 CallFun DelegateObj2 = new CallFun(MathsOprations.DivFun);
19
20 2-->委托使用:
21 //定义委托
22 public delegate int CallFun(int a, int b);
23 class MathsOperations
24 {
25 public int MulFun(int a, int b)
26 {
27 return a * b;
28 }
29 public int DivFun(int a, int b)
30 {
31 return a / b;
32 }
33 }
34
35 //实例化委托1(乘法)
36 CallFun DelegateObj1=new CallFun(MathsOprations.MulFun);
37 //使用委托
38 Console.WriteLine(DelegateObj1(2, 4));
39 //实例化委托2(除法)
40 CallFun DelegateObj2 = new CallFun(MathsOprations.DivFun);
41 //使用委托
42 Console.WriteLine(DelegateObj2(4, 2));
43 Console.ReadLine();
44
3.多播委托:
一个委托中可有多个方法
Delegate string delegateTest(string s);
delegateTest dt = new delegateTest(f1)
delegateTest dt2 = new delegateTest(f3)
dt = dt+dt2;
dt += new delegateTest(f2)
多播委托的使用:
//定义委托
public delegate void CallFun(int a, int b);
class MathsOprations
{
public static int result;
public static void MulFun(int i, int j)
{
result = i * j;
}
public static void DivFun(int i, int j)
{
result = result *(i / j);
}
}
//实例化委托
CallFun DelegateObj = new CallFun(MathsOprations.MulFun);
//多播委托
DelegateObj += new CallFun(MathsOprations.DivFun);
//调用多播委托
DelegateObj(9, 3);
System.Console.WriteLine("结果是:{0}", MathsOprations.result);
Console.ReadLine();
4.自定义事件
使用C#中的事件,对象可以将关于事件或已发生变化的信息通知其他对象把事件信息通知其他对象的对象称为发布方注册到事件的对象称为订户
步骤
1.定义事件
2.给对象预订该事件
3.通知事件的订户
我们可以通过自定义一个事件来进一步了解事件与委托的处理原理:
首先用一个死循环来模拟监听,我们把这个方法放入UserInputMonitor类中,当然这是一个公共类:
public void Run()
{
//finished永远是false,所以永远循环
bool finished = false;
do
{
if (Console.ReadLine() == "h")
{
//在这里使用这个事件,格式就是委托的格式,事件发生人是本类,新实例化一个空事件类传递参数。
OnUserRequest(this, new EventArgs());
}
} while (!finished);
}
自定义事件:
(1) 定义一个委托,可以放在类外,也可以放在类内,好像一个方法指针,包含指定的事件发生对象和描述事件本身的事件对象
public delegate void UserRequest(object sender, EventArgs e); 我们把它放在类外.
(2)自定义一个事件,不是系统本身的,如click!,要放在类内,而且必须指定委托
public event UserRequest OnUserRequest;
此代码不断的要求用户输入字符,如果输入的结果是h,则触发OnUserRequest事件,事件的触发者是本身(this),事件细节无(没有传递任何参数的EventArgs实例)。我们给这个类取名为UserInputMonitor。
我们还要定义一个Client类,在类中定义一个方法。
private void ShowMessage(object sender,EventArgs e)
{
Console.WriteLine("HaHa!!");
}
最后要做的是把这个方法和事件联系起来(订阅事件),我们把它写到Client类的构造函数里。
public Client(UserInputMonitor m)
{
m.OnUserRequest+=new UserRequest(this.ShowMessage);
}
好了,我们下面来运行它了,
(1)首先得实例化UserInputMonitor类
UserInputMonitor monitor=new UserInputMonitor();
(2)下面创建客户端的实例。
Client aa = new Client(monitor);
(3)最后让monitor开始监听事件。
monitor.run();
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 namespace ConsoleApplication1
5 {
6 //定义一个委托,可以放在类外,也可以放在类内,好像一个方法指针,包含指定的事件发生对象和描述事件本身的事件对象
7 public delegate void UserRequest(object sender, EventArgs e);
8
9 public class UserInputMonitor
10 {
11
12 //自定义一个事件,不是系统本身的,如click!,要放在类内,而且必须指定委托
13 public event UserRequest OnUserRequest;
14 //定义一个死循环
15 public void Run()
16 {
17 //finished永远是false,所以永远循环
18 bool finished = false;
19 do
20 {
21 if (Console.ReadLine() == "h")
22 {
23 //在这里使用这个事件,格式就是委托的格式,事件发生人就是本类,新实例化一个空事件类传递参数。
24 OnUserRequest(this, new EventArgs());
25 }
26 } while (!finished);
27 }
28 }
29 public class Client
30 {
31 public Client(UserInputMonitor m)
32 {
33 //订阅方法
34 m.OnUserRequest+=new UserRequest(this.ShowMessage);
35 }
36
37 //定义一个方法
38 private void ShowMessage(object sender, EventArgs e)
39 {
40 Console.WriteLine("HaHa!!");
41 }
42 }
43
44 class Program
45 {
46 static void Main()
47 {
48 //实例化监听对象
49 UserInputMonitor monitor = new UserInputMonitor();
50 //实例化客户端,实现订阅
51 Client aa = new Client(monitor);
52 //运行
53 monitor.Run();
54 }
55 }
56 }
57