前言
C# 好用,快速开发,但是有的时候里面的概念却让人一头雾水。
事件还好理解,但是委托却困扰了我好久,尤其是「delegate」、「event」、「Action<>」、「Func<>」以及各种注册方法,下面根据我的使用解释一下这个问题。
1、基本概念
1)委托(Delegate)可以为函数指针的升级版
先看看书本上给的概念:委托(delegate)是一种知道如何调用方法的对象。委托类型(delegate type)定义了一种委托实例(delegate instance)可以调用的方法。具体来说,它定义了方法的返回类型(return type)和参数类型(parameter type)。
说白了委托,就像一个「通讯录」里面存储了很多联系人「方法」的电话一样。
2)事件(Event)是委托的安全版本
事件是委托的一种表现形式,提供了更好更安全的封装形式。
3)Action<>是无返回值的泛型委托
「Action<>」是.NET 中预定义的一种委托类型,专门用于处理无返回值的方法。
4) Func<> 是区别于「Action<>」,是一种有返回值的泛型委托
5)总结
经过概念的对比,在编程中最佳的选择方式是:事件通知 → Event、简单回调 → Action<>、数据转换 → Func<>、复杂逻辑 → 自定义 Delegate。
2、注册方法
委托事件的注册方法也有很多种,比如:+=、-=、=、AddListener、Invoke 等方法,下面介绍一个各种注册方法的使用场景以及区别。
1)+= ,是一种最常用的注册方法,用于向委托或事件添加
2)-=,与 += 相对应的移除操作,用于从委托或事件移除
3)=,直接赋值,会覆盖掉之前「+=」的所有注册,可以理解为初始化或者清空
4)AddListener,Unity 里特有的,用于「UnityEvent」专用注册的方法
5)Invoke,显示调用委托或事件的方法,这个方法我在工作中用到的比较多
6)使用建议:订阅用+=,取消用-=,调用用 Invoke(),Unity 用 AddListener/RemoveListener
7)C# 委托事件的声明周期如下图所示。
3、应用场景
1)事件驱动编程
2)回调函数
3)函数式编程
4、常见问题
1)内存泄漏,一般是忘记取消订阅了
2)异常处理,尤其是多委托中的异常处理
3)线程安全问题
4)一种常用的实践模板
public classSafeEventManager : IDisposable{ privateevent Action<string> _dataChanged; privatereadonlyobject _lock = newobject(); // 安全的事件订阅 public void Subscribe(Action<string> handler) { lock (_lock) { _dataChanged += handler; } } // 安全的事件触发(异常隔离) public void SafeInvoke(string data) { Action<string> temp; lock (_lock) { temp = _dataChanged; } if (temp != null) { foreach (Action<string> handler in temp.GetInvocationList()) { try { handler(data); } catch (Exception ex) { /* 记录异常但继续 */ } } } } public void Dispose() { lock (_lock) { _dataChanged = null; } }}5、C# 委托事件学习路径与进阶
你是 C程序员吗?你的委托和事件用的怎么样?其实直到现在遇到这块内容时,我也会翻翻文档,小心谨慎,你呢? 关键词
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:全小鱼
出处:zhihu.com/question/62183440/answer/1932353712346632643
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!
方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注【加群】
推荐阅读
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!