在.NET中定义“委托”需要用到delegate关键字,它是存有对某个方法的引用的一种引用类型变量,类似于 C 或 C++ 中函数的指针。“委托”主要有两大作用:
(相关资料图)
(1)将方法当作参数传递
(2)方法的一种多态(类似于一个方法模板,可以匹配很多个方法)
下面,给出一个展现了上述两大作用的委托代码示例:
//定义一个委托 public delegate int MyDelegate(int x, int y); //与委托匹配的一个方法 public static int Add(int a, int b) { return a + b; } //与委托匹配的另一个方法 public static int Reduce(int a, int b) { return a - b; } //示例:将委托/方法当参数传递 public static int Test(MyDelegate MD) { return MD(10, 20); } static void Main(string[] args) { int a, b, x, y; MyDelegate md; //将委托指向Add这个方法,并进行相关操作 md = Add; a = md(1, 2); b = Test(md); //再将委托指向Reduce这个方法,并进行相关操作 md = Reduce; x = md(7, 2); y = Test(md); Console.WriteLine($"1+2={a},10+20={b},7-2={x},10-20={y}"); Console.ReadLine(); }
执行以上程序,输出结果如下:
1+2=3,10+20=30,7-2=5,10-20=-10
委托也可以使用+=/-=来实现“发布/订阅”模式,示例代码如下:
//定义一个委托 public delegate void MyDelegate1(int x); public static void Method1(int a) { Console.WriteLine($"a={a}"); } public static void Method2(int b) { Console.WriteLine($"b={b}"); } static void Main(string[] args) { MyDelegate1 md = null; md += Method1; md += Method2; md(35); Console.ReadLine(); }
以上程序输出如下:
a=35
b=35
但是委托有一个弊端,它可以使用“=”将所有已经订阅的取消,只保留=后的这一个订阅。
为了解决这个弊端,事件event应运而生。
2事件-概念的引出事件event是一种特殊的委托,它只能+=,-=,不能直接用=。
event在定义类中(发布者)是可以直接=的,但是在其他类中(订阅者)就只能+= -=了,也就是说发布者发布一个事件后,订阅者针对他只能进行自身的订阅和取消。
下面是定义一个事件的代码:
//定义一个委托 public delegate void MyDelegate1(int x); //定义一个事件 public event MyDelegate1 emd;
经过长久的经验积累后,人们发现,绝大多数事件的定义,是用public delegate void XXX(object sender, EventArgs e);这样一个委托原型进行定义的,是一件重复性的工作,于是,EventHandler应运而生。它的出现就是为了避免这种重复性工作,并建议尽量使用该类型作为事件的原型。
//@sender: 引发事件的对象//@e: 传递的参数public delegate void EventHandler(object sender, EventArgs e);//使用public event EventHandler emd;
下面给出一个使用事件的具体示例:
public class Demo { public event EventHandler emd; public void RaiseEvent() { emd(this, EventArgs.Empty); } } static void Main(string[] args) { var instance = new Demo(); instance.emd += (sender, arg) => { Console.WriteLine("执行事件1!"); }; instance.emd += (sender, arg) => { Console.WriteLine("执行事件2!"); }; instance.RaiseEvent(); Console.ReadLine(); }
这里我们先定义一个Demo类,其内部有个事件是emd,我们给他开放了一个接口RaiseEvent,如果谁敢调用它,那么,它就触发报警事件emd。
这里模拟了2个订阅者,分别处理报警事件emd。
程序执行结果如下:
执行事件1!
执行事件2!
同时,我们也可以看出:事件是按照+=的订阅先后顺序执行的。
3事件-关于异常现在,我们在第一个订阅者中加入异常,如下:
instance.emd += (sender, arg) => { Console.WriteLine("执行事件1!"); throw new Exception("执行事件1,错误"); };
执行后发现,第1个订阅者事件触发抛出异常后,第2个订阅者的事件没有执行。
可见,如果你想让所有订阅者都执行处理的话,那每个订阅者必须在订阅程序内自己处理好异常,不能抛出来!
4事件-关于异步如果事件的订阅者中有一个是“异步”处理,又会是什么情况?
下面我们把第1个订阅者改为异步处理,代码如下:
instance.emd += async (sender, arg) => { Console.WriteLine("执行事件1!"); await Task.Delay(1000); Console.WriteLine("执行事件1!完毕"); };
执行后输出如下:执行事件1!
执行事件2!
执行事件1!完毕
可见,异步的事件处理没有阻塞进程,很好的起到了异步方法的作用。
5委托-Func与Action本文最开始探讨委托,然后直接顺到了事件的相关话题上。其实,关于委托还有一个重点话题漏掉了,那就是Func与Action。
在委托delegate出现了很久以后,微软的.NET设计者们终于领悟到,其实所有的委托定义都可以归纳并简化成只用Func与Action这两个语法糖来表示。其中,Func代表有返回值的委托,Action代表无返回值的委托。有了它们两,我们以后就不再需要用关键字delegate来定义委托了。
同时,若再用lambda表达式取代被委托指向的具体方法,则整个委托的“定义+赋值”两步将大大简化(lambda表达式本来也是方法定义的一种简化形式)。
下面,把最开始委托章节中关于加减法的程序代码,用Func与lambda表达式进行简化改造,改造后的代码如下:
//示例:将委托/方法当参数传递 public static int Test(FuncMD) { return MD(10, 20); } static void Main(string[] args) { int a, b, x, y; Func md; //将委托指向加法,并进行相关操作 md = (t, v) => t + v; a = md(1, 2); b = Test(md); //再将委托指向减法,并进行相关操作 md = (t, v) => t - v; x = md(7, 2); y = Test(md); Console.WriteLine($"1+2={a},10+20={b},7-2={x},10-20={y}"); Console.ReadLine(); }
是不是代码大大简化了?简化了哪些内容,你可以前后对比一下...(本文完)
标签:
- 世界观焦点:智慧医疗”能够实现医疗管理和服... 2022-12-15 18:29:15
- 【全球速看料】pr视频软件如何学习(pr视频软... 2022-12-15 18:29:15
- 当前时讯:哥伦比亚广播公司推出幽灵之夏 2022-12-15 18:29:15
- 环球观热点:不愿给电池厂打工 多车企投钱自... 2022-12-15 18:29:15
- 特斯拉新款Model 3实车内饰曝光!两款车型售价上涨 2023-04-23 09:25:24
- 网红“减肥针”不是想打就能打 2023-04-23 08:58:36
- 每日速看!万商云集“链”全球 2023-04-23 09:18:34
- 世界热点!中国援喀麦隆雅温得医疗分队举行义诊 2023-04-23 08:53:03
- 快船主场输38个罚球,船记:威少篮下17投零罚... 2023-04-23 08:37:01
- 每日头条!word裁剪图片形状为正五边形(word裁... 2023-04-23 08:27:09
- 消息!闲鱼上怎么赚钱(闲鱼怎么赚钱) 2023-04-23 08:23:02
- 大姨妈不能碰的12种食物_来大姨妈能吃菠萝吗 ... 2023-04-23 08:06:52
- 追梦解禁后加强与其身体对抗?小萨:不会 还... 2023-04-23 07:54:26
- 第28个世界读书日|作为文化富矿的山东,还有... 2023-04-23 07:28:32
- 牛黄解毒片的功效与作用_牛黄清心丸的功效与作用 2023-04-23 07:07:19
- 有代沟什么意思_代沟什么意思_世界讯息 2023-04-23 07:07:14
- 世界微资讯!精选30余款菜肴推荐,时令食材搭... 2023-04-23 06:35:55
- 模拟经营、现场互动,苏州市相城区创业培训班... 2023-04-23 06:13:13
- 世界消息!车子碰撞保险公司怎么理赔的 2023-04-23 06:13:59
- 世界头条:2023五一天津解放桥怎么去?坐地铁... 2023-04-23 06:05:42
- 2023天津解放桥开桥时间是几点到几点 2023-04-23 06:21:13
- 每日视点!2023五一假期天津解放桥开桥只有5月... 2023-04-23 06:15:51
- 2023天津五一海河游船船票开售时间(附购票入... 2023-04-23 06:05:56
- 法师多肉可以露天养吗 春夏之交带锦的法师还... 2023-04-23 05:57:59
- 全球即时看!A股:这轮下跌或会持续很长时间 2023-04-23 06:01:07
- 尘世羁沧海月明完整版_尘世羁 2023-04-23 05:00:21
- 【热闻】4月21号后要准备2644点券?公孙离机甲... 2023-04-23 05:14:23
- 白鳞鲑鱼食谱_新鲜的白鳞鲑鱼在哪钓_当前看点 2023-04-23 04:31:05
- 全球快看:罗伊斯好惨一男的,续约一事悬而未... 2023-04-23 04:37:17
- 落雁沉鱼_关于落雁沉鱼的简介 2023-04-23 03:57:06
- 世界速读:无良商人的再度抉择,预告 2023-04-23 03:44:24
- 这群学生体验“农人”生活,在希望的田野耕耘未来 2023-04-23 03:28:18
- 三朝北盟会编点校本(三朝北盟会编) 2023-04-23 03:08:30
- 2023上海车展:全新林肯航海家上市 32.88-37.88万元 2023-04-23 02:53:34