回调函数与C#委托机制

回调函数

回调函数是一种有用的编程机制,就是通过函数指针调用的函数。C#里通过委托来提供回调函数的机制。不同于C/C++,委托确保回调方法是类型安全的,支持静态方法和类实例的成员方法,还允许顺序调用多个方法。

委托的内部构造

编译器实际上会为委托定义一个完整的类。类包含:

  • 4个方法:一个构造器、Invoke函数、BeginInvoke和EndInvoke。
  • 三个主要的字段 _target、 _methodPtr、 _invocationList
字段类型说明
_targetSystem.Object当委托对象包装一个静态方法时,这个字段为null。当委托包装一个实例方法时,这个字段引用的是回调方法要操作的对象。换言之,这个字段指出要给实例方法的隐式参数this的值。
_methodPtrSystem.IntPtr一个内部的IntPtr整数值,CLR用它标识要回调的方法。
_invocationListSystem.Object该字段通常为null。构造委托链时它引用一个委托数组。

可以看到fb1、fb2都是委托包装了静态方法,fb3是委托包装了实例方法。Invoke被调用时,如果是成员函数,委托会使用使用私有字段_target和_methodPtr在指定对象上调用包装好的回调方法。

在这里插入图片描述

委托链

如果委托链中只有一个委托fb1那么内部的成员变量如下。如果委托链中有多个委托,那么成员变量如下。在fbChain引用的委托上调用Invoke时,该委托发现私有字段_invocationList不为null,所以会执行一个循环来遍历数组中的所有元素,并依次调用每个委托包装的方法。

委托链的局限性,除了最后一个委托中的返回值,其他回调方法的返回值都会被丢弃。如果调用的委托中有一个抛出了异常或者阻塞了相当长时间,链中后续的所有对象都调用不了。
在这里插入图片描述
在这里插入图片描述

注意事项

  • 一个类型中通过委托带来调用另一个类型的私有成员,只委托对象是由具有足够安全性/可访问性的代码创建的,便没有问题。
  • 用lambda表达式进行匿名函数委托,实际上会生成一个类。并将使用到的局部变量传递到这个类的字段内。这实际延长了引用对象的生命周期。在大多数应用程序中不是大问题。但有时要注意下。

参考

  • 《CLR via C#(第四版)》
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值