分享
 
 
 

对.Net事件委托的深入分析

王朝c#·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

“委托”机制的“委托”到底是什么意思呢,《高级汉语大词典》中是如下解释的:托付给别的人或机构办理。要说生活中的意思其实大家都能理解,无非是“当某人(机构)需要完成一件自己不能或不应该完成的事情的时候,此人(机构)物色一个合适的且有能力完成此事的人选,然后提供必要的信息,将此事委托给物色到的人(机构)来完成。”

软件的对象方法其实是对现实世界的模拟,你可能会想现实世界里的委托哪有这么多呢?这么重要呢?其实你也许没有注重到老板把厚厚的一摞资料摔在你的案头让你无论如何在×月×日前交活,这不就是一种委托吗?当然也许没有委托书(和委任状),但它就是委托。这样看委托是不是就非常重要了,它甚至是构成现实社会的基础机制之一。

从这个意义上理解委托机制的重要性我想应该是足够了。委托机制是促使事件发送与事件接受的一种对接策略,对象对四周信号的反应或在一定环境中所具备的对其它对象的通知行为的响应则被描述成所谓的“事件”,这可以类比人对四周世界反馈产生信号的能力。

委托就是一种定向信号流:指定产生、接受信号者并产生信号反馈的技术。

我可爱的小女儿才刚刚学会说话就在饭桌上支使她可怜的“老”爸:爸爸,把我的小勺子拿来。我接到“信号”立即屁颠屁颠地跑到厨房拿到勺子送到女儿的小手上,一个“委托”完成的非常漂亮,而女儿则无须知道我在什么地方、如何拿到勺子,她只管接受到我给她专门买的小勺子就行,否则,她就要仰着小脸“哇哇”大哭了。

先说说事件委托的基础。

为了说明问题我设计了一个窗体还有几个按钮的示例DelegateDemo1项目,以便可以直观感受委托的基本用法。

至于委托在.Net中的实现,编译器会自动生成一个完整的类定义:一个构造器,Invoke,BeginInvoke,以及EndInvoke。

C#2003中隐式使用Invoke(其显式调用会报错)会让我们误解有一个以委托名称为名称的函数,其实没有,它只是隐式使用Invoke方法。而VB.net包括最新的VB.net2005均可以采取两种方法(显式或隐式)使用Invoke方法。我比较喜欢显式使用它,因为这样比较贴近事物的本质。

回到示例,代码如下(使用VB.net2003并出去VS自动生成的代码):

1 Public Class Form1Class Form1

2

3 Inherits System.Windows.Forms.Form

4

5 PRivate Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click, Button2.Click, Button4.Click

6

7 Select Case CType(sender, Button).Name

8

9 Case "Button1"

10

11 MessageBox.Show("你点击了Button1!", "委托提示", MessageBoxButtons.OK)

12

13 Case "Button2"

14

15 MessageBox.Show("你点击了Button2!", "委托提示", MessageBoxButtons.OK)

16

17 Case "Button3"

18

19 MessageBox.Show("你点击了Button3!", "委托提示", MessageBoxButtons.OK)

20

21 Case "Button4"

22

23 MessageBox.Show("你点击了Button4!", "委托提示", MessageBoxButtons.OK)

24

25 End Select

26

27 End Sub

28

29 Private Sub Button2_Click()Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

30

31 MessageBox.Show("Button2的Click事件,注重执行顺序!", "委托提示", MessageBoxButtons.OK)

32

33 End Sub

34

35 Private Sub Button3_Click()Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

36

37 Dim Demohandler1 As DemoHandler

38

39 Demohandler1 = AddressOf Button1_Click

40

41 Demohandler1.Invoke(sender, e)

42

43 Dim Demohandler2 As DemoHandler

44

45 Demohandler2 = AddressOf Button2_Click

46

47 Demohandler2(sender, e)

48

49

50

51 End Sub

52

53 Private Sub Button4_Click()Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

54

55 End Sub

56

57 Private Sub Button5_Click()Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click

58

59 End Sub

60

61 Private Sub Form1_DoubleClick()Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick, Button5.Click

62

63 If TypeOf sender Is Button Then

64

65 If MessageBox.Show("你确定退出吗?", "退出提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) = DialogResult.Yes Then

66

67 Me.Close()

68

69 Else : Exit Sub

70

71 End If

72

73 Else : Me.Close()

74

75 End If

76

77 End Sub

78

79End Class

80

Button1按钮的click事件的代码只需看看Handles子句,不仅有Button1.Click还有Button2.Click, Button4.Click,MSDN上说:在过程声明结尾处使用Handles要害字将使其处理由使用 WithEvents 要害字声明的对象变量所引发的事件。也可以在派生类中使用Handles要害字处理基类的事件。其实Handles子句答应任何与事件的参数签名相符的过程来响应这个事件。这实际上就是委托。在编译时间,.NET Framework用你的事件名称创建一个委托类,只是在结尾添加“EventHandler”字样。换言之,事件是使用委托来实现的,委托是面向对象函数指针的一种形式,它答应通过对函数进行引用的方法来间接地调用该函数。

用Ildasm.exe反汇编DelegateDemo1.exe,请看下图:

双击set_Button1方法或其他set_...方法,你都可以看到有System.EventHandler类出现。.NET Framework 中的事件模型基于具有事件委托,System.EventHandler将事件与事件处理程序连接。

Button1的Click事件过程中的Select Case…End Select功能是根据点击按钮的名称来选择事件处理程序。

Button3的Click事件过程要好好看看的。如下表:

语 句

释 义

Dim Demohandler1 As DemoHandler

定义一个DemoHandler委托的实例,DemoHandler可以换成 EventHandler

Demohandler1 = AddressOf Button1_Click

AddressOf可以认为就是将该委托和Button1_Click绑定

Demohandler1.Invoke(sender, e)

显式使用委托的Invoke方法调用事件处理程序

Dim Demohandler2 As DemoHandler

定义一个DemoHandler委托的实例,DemoHandler2

Demohandler2 = AddressOf Button2_Click

同上AddressOf

Demohandler2(sender, e)

隐式使用委托的Invoke方法调用事件处理程序

Button4按钮的click事件过程为空,因为在Button1_Click的Handles子句中已经注册,且由于它们的事件签名完全一致,故调用Button1_Click事件处理过程。

Button5按钮的click事件过程也为空,不要着急,下面的Form1_DoubleClick事件处理过程的Handles子句中注册了Button5,所以Button5的click事件的事件处理程序调用Form1的DoubleClick事件的事件处理程序。

在Form1的DoubleClick事件处理过程使用对控件类型的判定来选择处理方式。

我不说你也看出来了,这样写代码,就可以将一些本来需要重复多次的代码省去,符合重构的思想,使得代码尽量简约而由不失可读性。

现实生活中委托别人办的事能不能办好取决于以下两个方面:

1、是否委托给了合适的人;

2、是否把解决委托事件所需的正确和必要的信息传递给了它。

比如女儿委托我拿勺子,这个委托是相当成功的,因为她委托给了我(人选合适)且明确要她的小勺(正确和必要的信息传递)。

对应到.Net框架中的委托,一是要有委托对象,二是要签名相符。

项目编译运行后,点击Button3按钮有如下图显示:

点击“确定”后有:

点击“退出”Button5按钮有:

(注:以上内容描述多有个人理解的表述,欢迎大家批评指正,如有时间我会继续写如多路广播委托及使用委托的需求方面的内容)

备注:

引用:(下面这段是我看到过对委托概念及特点最为言简意赅的描述之一)

委托是用来处理其他语言(如 C++、Pascal 和 Modula)需用函数指针来处理的情况的。不过与 C++ 函数指针不同,委托是完全面对对象的;另外,C++ 指针仅指向成员函数,而委托同时封装了对象实例和方法。 委托声明定义一个从 System.Delegate 类派生的类。委托实例封装一个调用列表,该列表列出一个或多个方法,其中每个方法均作为一个可调用实体来引用。对于实例方法,可调用实体由该方法和一个相关联的实例组成。对于静态方法,可调用实体仅由一个方法组成。用一个适当的参数集来调用一个委托实例,就是用此给定的参数集来调用该委托实例的每个可调用实体。

委托实例的一个有趣且有用的属性是:它不知道也不关心它所封装的方法所属的类;它所关心的仅限于这些方法必须与委托的类型兼容(第 15.1 节)。这使委托非常适合于“匿名”调用。——《C#语言规范》Scott Wiltamuth 和 Anders Hejlsberg

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有