抖音粉丝群1
『7x24小时有问必答』

AI浪潮下的计算机行业——从业者现状与未来展望

前言

C# 好用,快速开发,但是有的时候里面的概念却让人一头雾水。
1.png
事件还好理解,但是委托却困扰了我好久,尤其是「delegate」、「event」、「Action<>」、「Func<>」以及各种注册方法,下面根据我的使用解释一下这个问题。

1、基本概念

2.png
1)委托(Delegate)可以为函数指针的升级版
先看看书本上给的概念:委托(delegate)是一种知道如何调用方法的对象。委托类型(delegate type)定义了一种委托实例(delegate instance)可以调用的方法。具体来说,它定义了方法的返回类型(return type)和参数类型(parameter type)。
说白了委托,就像一个「通讯录」里面存储了很多联系人「方法」的电话一样。
3.png
2)事件(Event)是委托的安全版本
事件是委托的一种表现形式,提供了更好更安全的封装形式。
4.png
3)Action<>是无返回值的泛型委托
「Action<>」是.NET 中预定义的一种委托类型,专门用于处理无返回值的方法
5.png
4) Func<> 是区别于「Action<>」,是一种有返回值的泛型委托
6.png
5)总结
经过概念的对比,在编程中最佳的选择方式是:事件通知 → Event、简单回调 → Action<>、数据转换 → Func<>、复杂逻辑 → 自定义 Delegate。

2、注册方法

委托事件的注册方法也有很多种,比如:+=、-=、=、AddListener、Invoke 等方法,下面介绍一个各种注册方法的使用场景以及区别。
7.png
1)+= ,是一种最常用的注册方法,用于向委托或事件添加
2)-=,与 += 相对应的移除操作,用于从委托或事件移除
3)=,直接赋值,会覆盖掉之前「+=」的所有注册,可以理解为初始化或者清空
4)AddListener,Unity 里特有的,用于「UnityEvent」专用注册的方法
5)Invoke,显示调用委托或事件的方法,这个方法我在工作中用到的比较多
6)使用建议:订阅用+=,取消用-=,调用用 Invoke(),Unity 用 AddListener/RemoveListener
7)C# 委托事件的声明周期如下图所示。
8.png

3、应用场景

9.png
1)事件驱动编程
10.png
2)回调函数
11.png
3)函数式编程
12.png

4、常见问题

13.png
1)内存泄漏,一般是忘记取消订阅了
14.png
2)异常处理,尤其是多委托中的异常处理
15.png
3)线程安全问题
16.png
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# 委托事件学习路径与进阶

17.png
在 C中委托和事件是  C的核心特性,也是相当比较高级的基础知识,掌握这部分对后续的学习和工作会有很大的帮助。
你是 C程序员吗?你的委托和事件用的怎么样?其实直到现在遇到这块内容时,我也会翻翻文档,小心谨慎,你呢?
关键词
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠]  社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:全小鱼
出处:zhihu.com/question/62183440/answer/1932353712346632643
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

END

方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群

推荐阅读

觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

收藏
点赞
分享
在看

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码