c#基础五 面向对象高级编程(委托与事件)
委托与事件
委托
委托是一种数据结构,提供类似c++语言中函数指针的功能,不同的是c++只能提供指向静态的方法,而委托除了可以指定静态的方法之外,还可以指定对象实例的方法。程序员可以利用委托在执行时期传入方法的名称,动态的决定欲调用的方法。
委托的最大特点是:它不关心自己引用的对象的类。任何对象中的方法都可以通过委托动态的调用,只是方法的参数类型和返回类型必须与委托的相同。
委托主要用在:(1)CallBack回调机制 (2)事件处理
委托步骤:
(1)声明delegate类型
如public delegate string MyDelegate(string name);委托没有方法体,当c#编译这段代码时,会为其生成一个新的类,该类继承自System.Delegate类,而类的名称是MyDelegate
(2)定义准备被委托调用的方法
此方法的参数类型、个数及参数的顺序都必须和delegate类型相同,如:
public static string FuntionA(string name){ 代码 }
(3)定义delegate类型的处理函数,并在此函数中通过delegate类型调用定义的方法。如:
public static void MethodA(MyDelegate Me){Console.WriteLine(Me("张三"));}
(4)创建实例,传入准备调用的方法名
MyDelegate a = new MyDelegate(FunctionA);//创建delegate的实例,a指向FunctionA方法的代码程序段
来看一个例子:
View Code
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 namespace delegatebybook
6 {
7 //第一步 声明委托
8 public delegate string MyDelegate(string name);
9
10 class Program
11 {
12 //第二步 定义被调用的方法
13 public static string FunctionA(string name)
14 {
15 return "A say hello to " + name;
16 }
17 public static string FunctionB(string name)
18 {
19 return "B say hello to " + name;
20 }
21 //第三步 定义delegate类型的处理函数,并在此函数中通过delegate类型调用步骤定义的方法
22 public static void MethodA(MyDelegate Me)
23 {
24 Console.WriteLine(Me("张三"));//执行到此,会自动调用FunctionA来执行
25 }
26 static void Main(string[] args)
27 {
28 //第四步:创建实例,传入准备调用的方法
29 MyDelegate a = new MyDelegate(FunctionA);
30 MyDelegate b = new MyDelegate(FunctionB);
31 MethodA(a);
32 MethodA(b);
33 Console.ReadLine();
34 }
35 }
36 }
结果:
A say hello to 张三
B say hello to 张三
事件:
事件是相应用户对鼠标、键盘操作或自动执行某个与事件关联的方法的行为。事件的签名通过委托类型来定义,为事件定义委托的常用形式为:public delegate MyEventHandler(Object sender,EventArgs e)
带事件的委托:
View Code
1 class TestEvent
2 {
3 //1.声明关于事件的委托
4 public delegate void MyEventHandler();
5 //2.声明事件
6 public event MyEventHandler Click;
7 //3.编写引发事件的函数
8 public void Trigger()
9 {
10 Click();
11 }
12 //4.编写事件处理程序
13 public void M1() { Console.WriteLine("Hi"); }
14 public void M2() { Console.WriteLine("Hi again"); }
15 public void M3() { Console.WriteLine("bye"); }
16 static void Main(string[] args)
17 {
18 //5.注册事件
19 TestEvent myEvent = new TestEvent();
20 myEvent.Click += new MyEventHandler(myEvent.M1);
21 myEvent.Click += new MyEventHandler(myEvent.M2);
22 myEvent.Click += new MyEventHandler(myEvent.M3);
23 //6.触发Click事件
24 myEvent.Trigger();
25 myEvent.Click -= new MyEventHandler(myEvent.M3);//取消对M3方法的注册
26 myEvent.Trigger();//重新引发事件
27 Console.ReadLine();
28 }
29 }
以下是在网上摘的代码,自己曾经对着敲了一遍,忘了具体哪篇博客了,呵呵(用猫和老鼠来解释委托事件,以及自定义参数的委托):
猫类:
View Code
1 class Cat
2 {
3 private string name;
4 public Cat(string name) { this.name = name; }
5
6 //1声明委托:可以有参数,也可以无参数
7 public delegate void CatShoutEventHandler(Object sender,CatShoutEventArgs args);
8 //2声明事件
9 public event CatShoutEventHandler CatShout;
10 //3定义触发函数(猫来)
11 public void Shout()
12 {
13 Console.WriteLine("喵,我是{0}",name);
14 if (CatShout != null)
15 {
16 //声明并实例化一个CatShoutEventArgs,并给Name属性赋值为猫的名字
17 CatShoutEventArgs e = new CatShoutEventArgs();
18 e.Name = this.name;
19 //重点
20 CatShout(this,e);
21 }
22 }
23 }
自定义参数类:
View Code
1 public class CatShoutEventArgs:EventArgs
2 {
3 private string name;
4 public string Name
5 {
6 get { return name; }
7 set{name = value;}
8 }
9 }
老鼠类:
View Code
1 class Mouse
2 {
3 private string name;
4 public Mouse(string name)
5 {
6 this.name = name;
7 }
8 //5定义一个接收函数,即事件触发时执行的函数(老鼠跑)
9 public void Run(object sender,CatShoutEventArgs args)
10 {
11 Console.WriteLine("老猫{0}来了,{1}快跑!",args.Name,name);
12 }
主类:
View Code
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Cat cat = new Cat("Tom");
6 Mouse m1 = new Mouse("Jerry");
7 Mouse m2 = new Mouse("Jack");
8
9 //4重点:注册事件
10 cat.CatShout += new Cat.CatShoutEventHandler(m1.Run);
11 cat.CatShout += new Cat.CatShoutEventHandler(m2.Run);
12
13 cat.Shout();
14 Console.ReadLine();
15 }
16 }
结果:
喵,我是Tom
老猫Tom来了,Jerry快跑!
老猫Tom来了,Jack快跑!
另外 http://www.cnblogs.com/BeginnerClassroom/archive/2009/01/11/1373689.html 这篇文章写得也很好。
用狗看家的例子,其实都是一个道理。
这是大致代码:
不带事件参数的:
1 //事件发送者
2 class Dog
3 {
4 //1.声明关于事件的委托;
5 public delegate void AlarmEventHandler(object sender, EventArgs e);
6
7 //2.声明事件;
8 public event AlarmEventHandler Alarm;
9
10 //3.编写引发事件的函数;
11 public void OnAlarm()
12 {
13 if (this.Alarm != null)
14 {
15 Console.WriteLine("\n狗报警: 有小偷进来了,汪汪~~~~~~~");
16 this.Alarm(this, new EventArgs()); //发出警报
17 }
18 }
19 }
20
21 //事件接收者
22 class Host
23 {
24 //4.编写事件处理程序
25 void HostHandleAlarm(object sender, EventArgs e)
26 {
27 Console.WriteLine("主 人: 抓住了小偷!");
28 }
29
30 //5.注册事件处理程序
31 public Host(Dog dog)
32 {
33 dog.Alarm += new Dog.AlarmEventHandler(HostHandleAlarm);
34 }
35 }
36
37 //6.现在来触发事件
38 class Program
39 {
40 static void Main(string[] args)
41 {
42 Dog dog = new Dog();
43 Host host = new Host(dog);
44
45 //当前时间,从2008年12月31日23:59:50开始计时
46 DateTime now = new DateTime(2008, 12, 31, 23, 59, 50);
47 DateTime midnight = new DateTime(2009, 1, 1, 0, 0, 0);
48
49 //等待午夜的到来
50 Console.WriteLine("时间一秒一秒地流逝... ");
51 while (now < midnight)
52 {
53 Console.WriteLine("当前时间: " + now);
54 System.Threading.Thread.Sleep(1000); //程序暂停一秒
55 now = now.AddSeconds(1); //时间增加一秒
56 }
57
58
59
60 //午夜零点小偷到达,看门狗引发Alarm事件
61 Console.WriteLine("\n月黑风高的午夜: " + now);
62 Console.WriteLine("小偷悄悄地摸进了主人的屋内... ");
63 dog.OnAlarm();
64 }
65 }
带事件参数的:
View Code
1 //事件参数
2
3 public class NumberOfThiefEventArgs : EventArgs
4 {
5 public int numberOfThief;
6
7 //构造函数
8 public NumberOfThiefEventArgs(int number)
9 {
10 numberOfThief = number;
11 }
12 }
13
14 //事件发送者
15 class Dog
16 {
17 //1.声明关于事件的委托;
18 public delegate void AlarmEventHandler(object sender, NumberOfThiefEventArgs e);
19
20 //2.声明事件;
21 public event AlarmEventHandler Alarm;
22
23 //3.编写引发事件的函数,注意多了个参数;
24 public void OnAlarm(NumberOfThiefEventArgs e)
25 {
26 if (this.Alarm != null)
27 {
28 Console.WriteLine("\n狗报警: 有小偷进来了,汪汪~~~~~~~\n");
29 this.Alarm(this, e);
30 }
31 }
32 }
33
34 //事件接收者
35 class Host
36 {
37 //4.编写事件处理程序,参数中包含着numberOfThief信息
38 void HostHandleAlarm(object sender, NumberOfThiefEventArgs e)
39 {
40 if (e.numberOfThief <= 1)
41 {
42 Console.WriteLine("主 人: 抓住了小偷!");
43 }
44 else
45 {
46 Console.WriteLine("主 人:打110报警,我家来了{0}个小偷!", e.numberOfThief);
47 }
48 }
49
50 //5.注册事件处理程序
51 public Host(Dog dog)
52 {
53 dog.Alarm += new Dog.AlarmEventHandler(HostHandleAlarm);
54 }
55 }
56
57 //6.现在来触发事件
58 class Program
59 {
60 static void Main(string[] args)
61 {
62 Dog dog = new Dog();
63 Host host = new Host(dog);
64
65 //当前时间,从2008年12月31日23:59:50开始计时
66 DateTime now = new DateTime(2008, 12, 31, 23, 59, 50);
67 DateTime midnight = new DateTime(2009, 1, 1, 0, 0, 0);
68
69 //等待午夜的到来
70 Console.WriteLine("时间一秒一秒地流逝... ");
71 while (now < midnight)
72 {
73 Console.WriteLine("当前时间: " + now);
74 System.Threading.Thread.Sleep(1000); //程序暂停一秒
75 now = now.AddSeconds(1); //时间增加一秒
76 }
77
78
79
80 //午夜零点小偷到达,看门狗引发Alarm事件
81 Console.WriteLine("\n月黑风高的午夜: " + now);
82 Console.WriteLine("小偷悄悄地摸进了主人的屋内... ");
83
84 //创建事件参数
85 NumberOfThiefEventArgs e = new NumberOfThiefEventArgs(3);
86 dog.OnAlarm(e);
87 }
88 }

浙公网安备 33010602011771号