委托、Lambda表达式和事件
委托是类型安全的类,它 定义了返回类型和参数的类型。 委托类不仅包含对方法的引用,也 可 以 包含对多个方法的引用。Lambda表达式与委托直接相关。 当参数是委托类型时,就 可以使用 Lambda表 达式实现委托引用的方法。
一、委托
当要把方法传送给其他方法时,需要使用委托。如,启动线程和任务,使用一些通用类库。如果要传递方法,就必须把方法的细节封装在一种新类型的对象中,即 委托。委托只是一种特殊类型的对象,其特殊之处在于,我们 以 前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址 。
1.声明委托:使用委托时,必须定义要使用的委托。对于委托,定义它就是告诉编译器这种类型的委托表示哪种类型的方法。然后,必须创建该委托的一个或多个实例。委托的类型安全性非常高,所以在定义委托时,必须给出它所表示的方法的签名和返回类型等 全部细节 。
定义委托的关键字:delegate
其语法类似于方法的 定义,但 没有方法体,定 义的 前面要加上关键字 delegate。 因为定义委托基本上是定 义一个新类,所 以 可以 在定义类的 任何相同 地方定义委托。也就是说,可 以 在另一个类的内部定义,也可以 在任何类的 外部定义,还可以 在名称空间中 把委托定义为顶层对象。 根据定义的 可见性,和 委托的 作用域,可 以 在委托的 定义上应用任意常见的 访问 修饰符:public,private,protected。定义好委托后,就可以创建它的一个实例,从而用它存储特定方法的细节。
实际上,定义一个委托,是指定义一个新类。委托实现为派生自基类System.MulticastDelegate的类,它又派生自基类System.Delegate。C#编译器能识别这个类,会使用其委托语法,因此我们不需要了解这个类的具体执行情况。但是在术语方面有一个问题。类有两个不同的术语,类表示较广义的定义,对象表示类的实例,但委托只有一个术语,在创建委托的实例时,所创建的委托的实例仍称为委托,必须从上下文中确定委托的确切含义。
2.使用委托:在 C#中 ,委 托在语法上`总是接受一个参数的 构造函 数,这个参数就是委托引
用的方法。 这个方法必须匹 配最初定义委托时的 签名。在任何代码中,都应提供委托实例的 名称,后 面的圆括号中 应包含调用该委托中的 方法时 使用的 任何等效参数。为了 减少输入量,只 要需要委托实例,就 可以只传送地址的名称。这称为委托推断。只要编译器可以 把委托实例解析为特定的类型,这 个C#特 性就是有效的。委托推断可以 在需要委托实例的 任何地方使用。 委托推断也可以 用于事件,因 为事件基于委托。委托的 一 个特征是它们的 类型是安全的,可 以 确保被调用的 方法的 签名是正确的。不关心在什么类型的 对象上调用该方法,甚 至不考虑该方法是静态方法,还是实例方法。给定委托的实例可以引用任何类型的任何对象上的实例方法或静态方法,只要方法的签名匹配于委托的签名即可。
3.示例
4.Action<T>和Func<T>委托:除了 为每个参数和返回 类型定义一个新委托类型之外,还可以 使 用Action<T>和Func<T>委托。泛型 Action<T>委 托表示引 用一个Void返回类型的方法。因为这个委托类存在不同的 变体,所 以 可以 传递至多 16种 不同的 参数类型。Func<T>委托可以以类似的方式使用。Func<T>允许调用带返回类型的方法,与Action<T>类似,Func<T>也定义了不同的变体,至多也可以传递16个参数类型和一个返回类型。还可以定义成委托类型的数组。
5.示例
6.多播委托:委托也可以 包含多 个方法。 这种委托称为多播委托。 如果调用多播委托,就 可以 按顺序连续调用多个方法。 为此,委 托的 签名就必须返回void,否则,就 只能得到委托调用的最后一个方法的结果。多播委托可以识别运算符+和+=以及-和-=来增加或删除委托的方法调用。通过一个委托调 用多 个方法还可能导 致一个大问 题。 多 播委托包含一个逐个调用的 委托集合。 如果通过委托调用的 其中 一个方法抛出 一 个异常,整个迭代就会停止。在这种情况下,为 了 避免这个问 题,应 自 己 迭代方法列表。 Delegate类 定义 GetInvocationList()方法,它 返回一个 Delegate对 象数组。 现在可以 使用这个委托调用与委托直接相关的 方法,捕 获异常,并继续下一次迭代。
7.匿名方法:匿名方法是用作委托的 参数的一段代码。用匿名方法定义委托的 语法与前面的定义并没有区别。不是把方法名赋予这个变量,而 是使用一段简单的 代码:它前面是关键字 de1egate,后 面是参数列表;匿名方法的 优点是减少了 要编写的 代码。 不必定义仅由 委托使用的 方法。 在为事件定义委托时,这是非常显然的 (本 章后面探讨事件)。 这有助于降低代码的复杂性,尤其是定义了 好几个事件时,代码会显得比 较简单。 使用匿名方法时,代 码执行得不太快。 编译器仍定义了 一个方法,该 方法只有一个 自 动指定的名称,我们不需要知道这个名称。在使用匿名方法时,必 须遵循两条规则。 在匿 名方法中 不能使用跳转语句oreak、 goto或continue )跳到该匿名方法的外部,反之亦然:匿 名方法外部的 跳转语旬不能跳到该匿名方法的内 部。在匿名方法内 部不能 访问 不安全的 代码。 另外,也 不能访问 在匿名方法外部使用的 ref和 out参数。 但可以 使用在匿名方法外部定义的其他变量。如果需要用匿名方法多次编写同 一个功能,就 不要使用匿名方法。从C#3.0开始,可 以 使用 Lambda表 达式替代匿名方法。
二、Lambda表达式
自C#3.0开 始,就 可以 使 用一 种新 语法 把实 现 代 码赋 予委 托:Lambda表 达 式。 只 要 有 委托 参 数类型的 地 方,就 可以 使 用 Lambda表 达式。
运算符:=>:左边列出需要的参数,右边定义了赋予Lambda变量的方法的实现代码
1.参数
2.多行代码
3.外部变量
三、事件
事件基于委托,为委托提供了一种发布/订阅机制。在架构内到处能看到事件。
1.事件发布程序
事 件。 作为一个约定,事件一般使用带两个参数的方法,其 中 第一个参数是一个对象,包含事件的发送者 ,第 二个参数提供了 事件的相关信息。 第二个参数随不同的事件类型而不同
2.事件监听器
+=:订阅
-=:取消订阅
3.弱事件
使用 WeekEventManager作 为发布程序和侦听 器之间的中 介。
1)弱事件管理器
2)事件侦听器
这部分个人感觉挺重要的。。。有一部分能明白,有一部分不明白。需要实战才能彻底熟悉吧~~等等机会,实战一把``