委托与回调的暧昧

从C++转到C#的人通常会被告知一件事情:委托相当于函数指针!这样说或许没什么错,但其实容易误导新人。应该知道的是,委托是一个对象,不是函数,也不是其他形式的存在,它就是一个对象,它只是定义的时候很像一个函数,但编译器会把它自动翻译成一个对象class,之所以用函数指针类比委托,是因为它看起来像个函数,它的主要能力就是通过一个函数展现出来的,但它能做的事情包括却不限于一个函数指针


委托中最重要的两个方法是invoke和beginInvoke,又引出了同步和异步调用的概念。Invoke很简单,是阻塞的同步调用,一种常用的使用场景就是在对象A中设置一个委托,从外部给他赋值,在需要的时候执行Invoke,用函数指针的形式实现一个回调,可以达到让对象A执行一段“计划之外”代码的目的。


说到beginInvoke,它最常见用法,是把委托当另外一个线程使用,定义好委托后直接beginInvoke(null, null),可以达到让另外一个线程去执行该委托代码的效果,这比自己去创建线程或者从线程池中启动线程去做这件事情要代码直观,还能直接使用调用作用域的局部变量,十分方便:

{
   int a, b// 调用作用域的局部变量
   ...
   Action action = new Action(() => {
       Console.WriteLine((a + b).ToString());// 可使用调用作用域的局部变量
   });
  
  action.BeginInvoke(null, null);// 等价于启用一个线程去执行相关代码
}


这种用法还能玩出更多花样来,比如给委托线程传入参数,比如让调用线程等待委托线程执行结束,这些功能和最基础的线程间通信是一个理儿,只不过委托把这些东西封装得更方便使用而已,此处不再多说。


这花样中有一个地方容易让人误会,就是beginInvoke传入的两个参数(至少),一个是AsyncCallback(就是一个委托),一个是object参数,为什么又要传一个委托,本来就是委托在执行了为什么又要传入一个委托,从字面上理解它又叫做回调,这不整人么这不是?!首先要明白,此委托是可传可不传的,它的行为也完全由你来定义,它不过就是在调用委托函数执行完毕以后,再执行的一个方法而已,没什么特别的,它把自己叫回调也行,委托也罢,反正就是这么回事儿,一点也不稀奇。


接下来就要说一下回调,这个概念早已如雷贯耳,我总感觉一些基础不太好的同学喜欢那这个词来修饰自己的素养,这么多年了,有时候我觉得它很神秘,又时候又似乎很简单,今天一定要撕开它的伪装,让大家看看,它一点也不神秘,它就是我让你做一件事,你做完了告诉我一声,你告诉我的这一声就是回调了。其实这样理解也多少有些误会,你可以不告诉我,你可以只是利用一些我才知道的资源做一点事情,那你这个行为我也可以美其名曰为回调;你甚至可以和我没有任何关系,在做完我要求你做的事情以后,硬生生的用我事先传给你的委托发起一个invoke操作,但操作的内容与我完全无关,我也可以死不要脸的把这个invoke叫做回调(看,我在这里给你一个回调,我的逼格很高哦)。一定要弄清楚的是:回调这个行为(过程、函数),是发生在你的线程里,是你的线程在执行这一个过程,而不是我的,所以一定不要被回调这个字面意思误导,认为是我的线程在调用这一段代码,当然你可以用一些技术手段达到类似的目的,比如你打开一个开关变量,让我可以走到你预先留下的代码段的,或者你激活事先埋伏在我身上的委托,让我自然而然的去做委托中你算计好的事情。冤冤相报就没完没了,但真相只有一个,回调是从你的线程上开始执行的!


前面说这么多都是我们自己再玩委托,其实.NET已经把它玩得炉火纯青了,想想linq,扩展方法,什么什么表达式各种show,但用法还是上面归纳的两种: 当函数指针用;当线程用
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在C#委托中,回调函数指的是将一个函数作为参数传递给另一个函数,并在需要的时候调用该函数。回调函数在执行完一些操作后,可以重新调用不属于它的某些东西。 举个例子,假设有两个类Text1和Text2,Text1类中有一个静态方法Begin,它接受一个委托类型的参数makesum add。在Begin方法中,我们可以看到在调用add时传入了a和b两个参数。而这个add方法实际上是Text2类中的静态方法with,它接受a和b两个参数,并在其中调用了Text1类中的shenm方法。这里with方法就是一个回调函数。 在使用委托时,我们可以通过实例化一个委托对象并传入对应的方法作为参数,然后在需要的时候通过委托对象调用回调函数。这种方式可以让我们在调用方法时动态地指定不同的操作逻辑,提高了代码的灵活性和可重用性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C#回调函数](https://blog.csdn.net/lfanyize/article/details/103150584)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [C# 中的委托事件和回调函数](https://blog.csdn.net/weixin_42105843/article/details/121243956)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值