C# 从1到Core--委托与事件,通宵都要看完这个前端关键技术点

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
img

正文

很自然想到采用类似Get和Set的方式避免上面的问题。既然委托可以像变量一样赋值,那么也可以通过参数来传值,将一个方法作为参数传递。

public class HRWithAddRemove { private SendDelegate sendDelegate; public void AddDelegate(SendDelegate sendDelegate) { this.sendDelegate += sendDelegate; //如果需要限制最多绑定一个,此处可以用=号 } public void RomoveDelegate(SendDelegate sendDelegate) { this.sendDelegate -= sendDelegate; } public void SendMessage(string msg) { sendDelegate(msg); } }

经过改造后的HR,SendDelegate方法被设置为了private,之后只能通过Add和Remove的方法进行方法绑定。

4.模拟多播委托机制


通过上面委托的表现来看,委托就像是保存了一个相同方法名的集合 List ,可以向集合中添加或移除方法,当调用这个委托的时候,会逐一调用该集合中的各个方法。

例如下面的代码( 注意这里假设SendDelegate只对应一个方法 ):

public class HR1 { public void Delegate(SendDelegate sendDelegate) { sendDelegateList = new List<SendDelegate> { sendDelegate }; //对应= } public void AddDelegate(SendDelegate sendDelegate) { sendDelegateList.Add(sendDelegate); //对应+= } public void RomoveDelegate(SendDelegate sendDelegate) { sendDelegateList.Remove(sendDelegate);//对应-= } public List<SendDelegate> sendDelegateList; public void SendMessage(string msg) { foreach (var item in sendDelegateList) { item(msg); } } }

二、C#1.0 引入事件

============

1.简单事件


如果既想使用-=和+=的方便,又想避免相关功能开闭的风险怎么办呢?可以使用事件:

public class HRWithEvent { public event SendDelegate sendDelegate; public void SendMessage(string msg) { sendDelegate(msg); } }

只是将SendDelegate前面添加了一个event标识,虽然它被设置为public,但如下代码却会给出错误提示: 事件“HRWithEvent.sendDelegate”只能出现在 += 或 -= 的左边(从类型“HRWithEvent”中使用时除外)

hr.sendDelegate = senderZS.Send; hr.sendDelegate("偷偷的发一条");

2.事件的访问器模式


上文为委托定义了Add和Remove方法,而事件支持这样的访问器模式,例如如下代码:

public class CustomerWithEventAddRemove { private event SendDelegate sendDelegate; public event SendDelegate SendDelegate { add { sendDelegate += value; } remove { sendDelegate -= value; } } public void SendMessage(string msg) { sendDelegate(msg); } }

可以像使用Get和Set方法一样,对事件的绑定与移除进行条件约束。

  1. 控制绑定事件的执行

当多个委托被绑定到事件之后,如果想精确控制各个委托的运行怎么办,比如返回值(虽然经常为void)、异常处理等。

第一章第4节通过一个List 模拟了多播委托的绑定。 会想到如果真能循环调用一个个已绑定的委托,就可以精确的进行控制了。那么这里说一下这样的方法:

public class HRWithEvent { public event SendDelegate sendDelegate; public void SendMessage(string msg) { //sendDelegate(msg); 此处不再一次性调用所有 if (sendDelegate != null) { Delegate[] delegates = sendDelegate.GetInvocationList(); //获取所有已绑定的委托 foreach (var item in delegates) { ((SendDelegate)item).Invoke(msg); //逐一调用 } } } }

这里通过Invoke方法逐一调用各个Delegate,从而实现对每一个Delegate的调用的控制。若需要异步调用,则可以通过BeginInvoke方法实现(.NET Core之后不再支持此方法,后面会介绍。)

((SendDelegate)item).BeginInvoke(msg,null,null);

  1. 标准的事件写法

.NET 事件委托的标准签名是:

void OnEventRaised(object sender, EventArgs args);

返回类型为 void。 事件基于委托,而且是多播委托。 参数列表包含两种参数:发件人和事件参数。 sender 的编译时类型为 System.Object

第二种参数通常是派生自 System.EventArgs 的类型(.NET Core 中已不强制要求继承自System.EventArgs,后面会说到)

将上面的例子修改一下,改成标准写法,大概是下面代码的样子:

public class HRWithEventStandard { public delegate void SendEventHandler(object sender, SendMsgArgs e); public event SendEventHandler Send; public void SendMessage(string msg) { var arg = new SendMsgArgs(msg); Send(this,arg); //arg.CancelRequested 为最后一个的值 因为覆盖 } } public class SendMsgArgs : EventArgs { public readonly string Msg = string.Empty; public bool CancelRequested { get; set; } public SendMsgArgs(string msg) { this.Msg = msg; } }

三、随着C#版本改变

==========

  1. C#2.0 泛型委托

C#2.0 的时候,随着泛型出现,支持了泛型委托,例如,在委托的签名中可以使用泛型,例如下面代码

public delegate string SendDelegate<T>(T message);

这样的委托适用于不同的参数类型,例如如下代码(注意使用的时候要对应具体的类型)

public delegate string SendDelegate<T>(T message); public class HR1 { public SendDelegate<string> sendDelegate1; public SendDelegate<int> sendDelegate2; public SendDelegate<DateTime> sendDelegate3; } public static class Sender1 { public static string Send1(string msg) { return ""; } public static string Send2(int msg) { return ""; } } public class Test { public void TestDemo() { HR1 hr1 = new HR1(); hr1.sendDelegate1 = Sender1.Send1; // 注意使用的时候要对应具体的类型 hr1.sendDelegate2 = new SendDelegate<int>(Sender1.Send2); hr1.sendDelegate3 = delegate (DateTime dateTime) { return dateTime.ToLongDateString(); }; } }

  1. C#2.0 delegate运算符

最后

今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!

可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-cRVr1ZIM-1713285138152)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值