你的位置:首页 > 软件开发 > ASP.net > [转载]C#深入分析委托与事件

[转载]C#深入分析委托与事件

发布时间:2016-12-07 23:00:11
原文出处:作者:风尘浪子原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html同类链接:http://www.cnblogs.com/SkySoot/archive/2012/04/05/24336 ...

[转载]C#深入分析委托与事件

原文出处:

作者:风尘浪子

原文链接:http://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html

同类链接:http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html

引言

本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单。

MulticastDelegate是System.Delegate的子类,它是一个特殊类,编译器和其他工具可以从此类派生,但是自定义类不能显式地从此类进行派生。它支持多路广播委托,并拥有一个带有链接的委托列表,在调用多路广播委托时,系统将按照调用列表中的委托出现顺序来同步调用这些委托。

MulticastDelegate具有两个常用属性:Method、Target。其中Method 用于获取委托所表示的方法Target 用于获取当前调用的类实例。

MulticastDelegate有以下几个常用方法:

方法名称说明
 Clone  创建委托的浅表副本。
 GetInvocationList  按照调用顺序返回此多路广播委托的调用列表。
 GetMethodImpl  返回由当前的 MulticastDelegate 表示的静态方法。
 GetObjectData  用序列化该实例所需的所有数据填充 SerializationInfo 对象。
 MemberwiseClone  创建当前 Object 的浅表副本。
 RemoveImpl  调用列表中移除与指定委托相等的元素

MulticastDelegate与Delegate给委托对象建立了强大的支持,下面向各位详细介绍一下委托的使用方式。

回到目录

 

三、委托使用方式

3.1 简单的委托

当建立委托对象时,委托的参数类型必须与委托方法相对应。只要向建立委托对象的构造函数中输入方法名称example.Method,委托就会直接绑定此方法。使用myDelegate.Invoke(string message),就能显式调用委托方法。但在实际的操作中,我们无须用到 Invoke 方法,而只要直接使用myDelegate(string message),就能调用委托方法。

[转载]C#深入分析委托与事件

 

3.2 带返回值的委托

当建立委托对象时,委托的返回值必须与委托方法相对应。使用下面的例子,方法将返回 “Hello Leslie” 。

[转载]C#深入分析委托与事件

 

3.3 多路广播委托

在第二节前曾经提过,委托类继承于MulticastDelegate,这使委托对象支持多路广播,即委托对象可以绑定多个方法。当输入参数后,每个方**按顺序进行迭代处理,并返回最后一个方法的计算结果。

运行结果

[转载]C#深入分析委托与事件

运行结果

[转载]C#深入分析委托与事件

 

开发 Observer 模式时借助委托,可以进一步简化开发的过程。由于委托对象支持多路广播,所以可以把Worker类省略。在WageManager类中建立了一个委托对象wageHandler,通过Attach与Detach方法可以分别加入或取消委托。如果观察者想对事物进行监测,只需要加入一个委托对象即可。记得在第二节曾经提过,委托的GetInvodationList方法能获取多路广播委托列表,在Execute方法中,就是通过去多路广播委托列表去判断所绑定的委托数量是否为0。

[转载]C#深入分析委托与事件

最后运行结果与上面的例子相同。

 

3.5 委托的协变与逆变

在 Framework 2.0 出现之前,委托协变这个概念还没有出现。此时因为委托是安全类型,它们不遵守继承的基础规则。即会这下面的情况:Manager 虽然是 Worker 的子类,但 GetWorkerHander 委托不能直接绑定 GetManager 方法,因为在委托当中它们的返回值 Manager 与 Worker 被视为完全无关的两个类型。

[转载]C#深入分析委托与事件

自从Framework 2.0 面试以后,委托协变的概念就应运而生,此时委托可以按照传统的继承规则进行转换。即 GetWorkerHandler 委托可以直接绑定 GetManager 方法。

[转载]C#深入分析委托与事件

委托逆变,是指委托方法的参数同样可以接收 “继承” 这个传统规则。像下面的例子,以 object 为参数的委托,可以接受任何 object 子类的对象作为参数。最后可以在处理方法中使用 is 对输入数据的类型进行判断,分别处理对不同的类型的对象。

[转载]C#深入分析委托与事件

运行结果

[转载]C#深入分析委托与事件

注意委托与其绑定方法的参数必须一至,即当 Handler 所输入的参数为 A 类型,其绑定方法 GetMessage 的参数也必须为 A 类或者 A 的父类 。相反,当绑定方法的参数为 A 的子类,系统也无法辨认。

运行结果

[转载]C#深入分析委托与事件

回到目录

四、深入解析事件

4.1 事件的由来

在介绍事件之前大家可以先看看下面的例子, PriceManager 负责对商品价格进行处理,当委托对象 GetPriceHandler 的返回值大于100元,按8.8折计算,低于100元按原价计算。

[转载]C#深入分析委托与事件

运行结果

[转载]C#深入分析委托与事件

观察运行的结果,如果把委托对象 GetPriceHandler 设置为 public ,外界可以直接调用 GetPriceHandler.Invoke 获取运行结果而移除了 GetPrice 方法的处理,这正是开发人员最不想看到的。

为了保存封装性,很多操作都需要加入AddHandler、RemoveHandler 这些相似的方法代码,这未免令人感到厌烦。

 

4.4 事件处理方法的绑定

在绑定事件处理方法的时候,事件出现在+=、-= 操作符的左边,对应的委托对象出现在+=、-= 操作符的右边。对应以上例子,事件提供了更简单的绑定方式,只需要在+=、-= 操作符的右方写上方法名称,系统就能自动辩认。

[转载]C#深入分析委托与事件

如果觉得编写 GetName 方法过于麻烦,你还可以使用匿名方法绑定事件的处理。

[转载]C#深入分析委托与事件

 

4.5 C#控件中的事件

在C#控件中存在多个的事件,像Click、TextChanged、SelectIndexChanged 等等,很多都是通过 EventHandler 委托绑定事件的处理方法的,EventHandler 可说是C#控件中最常见的委托 。

public delegate void EventHandler (Object sender, EventArgs e)

EventHandler 委托并无返回值,sender 代表引发事件的控件对象,e 代表由该事件生成的数据 。在ASP.NET中可以直接通过btn.Click+=new EventHandler(btn_onclick) 的方式为控件绑定处理方法。

[转载]C#深入分析委托与事件

更多时候,只需要在页面使用 OnClick=“btn_onclick" 方法,在编译的时候系统就会自动对事件处理方法进行绑定。

[转载]C#深入分析委托与事件

 

EventHandler 只是 EventHandler<TEventArgs> 泛型委托的一个简单例子。事实上,大家可以利用 EventHandler<TEventArgs> 构造出所需要的委托。

public delegate void EventHandler<TEventArgs> (Object sender, TEventArgs e)

在EventHandler<TEventArgs>中,sender代表事件源,e 代表派生自EventArgs类的事件参数。开发人员可以建立派生自EventArgs的类,从中加入需要使用到的事件参数,然后建立 EventHandler<TEventArgs> 委托。

下面的例子中,先建立一个派生自EventArgs的类MyEventArgs作为事件参数,然后在EventManager中建立事件myEvent , 通过 Execute 方法可以激发事件。最后在测试中绑定 myEvent 的处理方法 ShowMessage,在ShowMessage显示myEventArgs 的事件参数 Message。

[转载]C#深入分析委托与事件

运行结果

[转载]C#深入分析委托与事件

 

4.6 为用户控件建立事件

在ASP.NET开发中,页面往往会出现很多类似的控件与代码,开发人员可以通过用户控件来避免重复的代码。但往往同一个用户控件,在不同的页面中需要有不同的响应。此时为用户控件建立事件,便可轻松地解决此问题。

运行结果

[转载]C#深入分析委托与事件

 

使用控件已有的事件固然简单,但它限制了传送的参数类型,使开发人员无法传送额外的自定义参数。在结构比较复杂的用户控件中,使用已有的控件事件,显然不够方便,此时,您可以考虑为用户控件建立自定义事件。

运行结果

[转载]C#深入分析委托与事件

总是使用 delegate(){......} 的方式建立匿名方法,令人不禁感觉郁闷。于是从Framework 3.0 起, Lambda 表达式开始出现。

 

5.3 简单介绍泛型委托

在介绍 Lambda 表达式前,先介绍一下常用的几个泛型委托。

 

5.3.1 泛型委托 Predicate<T>

早在Framework 2.0 的时候,微软就为 List<T> 类添加了 Find、FindAll 、ForEach 等方法用作数据的查找。

public T Find ( Predicate<T> match)

 

5.3.2 泛型委托 Action

Action<T> 的使用方式与 Predicate<T> 相似,不同之处在于 Predicate<T> 返回值为 bool ,  Action<T> 的返回值为 void。

 

5.3.3 泛型委托 Func

委托 Func 与 Action 相似,同样支持 0~16 个参数,不同之处在于Func 必须具有返回值

public delegate TResult Func<TResult>()

 

5.4 揭开 Lambda 神秘的面纱

Lambda 的表达式的编写格式如下:

     x=> x * 1.5

 

例子三,定义一个Predicate<int>,当输入值大约等于1000则返回 true , 否则返回 false。与5.3.1的例子相比,Predicate<T>的绑定不需要显式建立一个方法,而是直接在Lambda表达式里完成,简洁方便了不少。

[转载]C#深入分析委托与事件

 

例子四,在计算商品的价格时,当商品重量超过30kg则打9折,其他按原价处理。此时可以使用Func<double,int,double>,参数1为商品原价,参数2为商品重量,最后返回值为 double 类型。

[转载]C#深入分析委托与事件


 

海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

原标题:[转载]C#深入分析委托与事件

关键词:C#

C#
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录