c语言sscanf函数的用法是什么
255
2022-09-19
通过IL分析C#中的委托、事件、Func、Action、Predicate之间的区别与联系
一直以来都是对于事件与委托比较混淆,而且不太会用。找了个时间,总结了一下,感觉清晰了很多。
先说一下个人理解的结论吧:
delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。
Action 与Func:这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。
首先了解一下, ILDasm中图标含义:
委托创建步骤:
一、事件与委托
新建一个事件委托测试项目:EventDelegateTest
具体代码如下:
namespace EventDelegateTest{ public class TestClass { public delegate int delegateAction(); public event delegateAction OnActionEvent; public delegateAction daNew; }}
编译代码后,使用 Visual Studio 2010自带的ILDASM.EXE:
打开该dll,可以看到如下信息:
从上图可以看出如下几点信息:
1、委托 public delegate int delegateAction();
在IL中是以类(delegateAction)的形式存在的
.NET将委托定义为一个密封类,派生自基类System.MulticastDelegate,并继承了基类的三个方法
2、public event delegateAction OnActionEvent;
在IL中不仅仅对应event OnActionEvent而且还对应一个field OnActionEvent;
而field OnActionEvent与 public delegateAction daNew生成的field daNew是一样的
都是以字段(field )的形式存在的。
双击event OnActionEvent可以看到如下信息:
在IL中事件被封装成了包含一个add_前缀和一个remove_前缀的的代码段。
其中,add_前缀的方法其实是通过调用Delegate.Combine()方法来实现的,组成了一个多播委托;remove_就是调用Delegate.Remove()方法,用于移除多播委托中的某个委托。
也就是说:事件其实就是一个特殊的多播委托
那么对于事件进行这一次封装有什么好处呢?
1、因为delegate可以支持的操作非常多,比如我们可以写onXXXChanged += aaaFunc,把某个函数指针挂载到这个委托上面,但是我们也可以简单粗暴地直接写onXXXChanged = aaaFunc,让这个委托只包含这一个函数指针。不过这样一来会产生一个安全问题:如果我们用onXXXChanged = aaaFunc这样的写法,那么会把这个委托已拥有的其他函数指针给覆盖掉,这大概不是定义onXXXChanged的程序员想要看到的结果。
小注:
虽然事件不能直接=某个函数,也不可以直接=null
2、还有一个问题就是onXXXChanged这个委托应该什么时候触发(即调用它所包含的函数指针)。从面向对象的角度来说,XXX改变了这个事实(即onXXXChaned的字面含义)应该由包含它的那个对象来决定。但实际上我们可以从这个对象的外部环境调用onXXXChanged,这既产生了安全问题也不符合面向对象的初衷。
说到这里对于事件与委托的管理算是说明白了,那么平时常用的Action与Func,与委托又有什么关系呢?
二、Action 与Func
Action 委托:封装一个方法,该方法具有参数(0到16个参数)并且不返回值。
具体形式如下:TResult> 委托:封装一个具有参数(0到16个参数)并返回 TResult 参数指定的类型值的方法。
具体形式如下:T2> 委托:封装一个方法,该方法具有两个参数并且不返回值为例)
从微软公布的源码中,可以看到,如下实现:
public Action
其余使用方式与委托变量一样。
2、Func(以Func
这两个其实说白了就是系统定义好的Delegate,他有很多重载的方法,便于各种应用情况下的调用。他在系统的System命名空间下,因此全局可见。
三、Predicate
是返回bool型的泛型委托,Predicate有且只有一个参数,返回值固定为bool。表示定义一组条件并确定指定对象是否符合这些条件的方法。此方法常在集合(Array 和 List
具体用法demo如下:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace IconTest{ public partial class Form2 : Form { Predicate
上例中说明了Predicate的使用,FindAll方法中,参数2即是一个Predicate,在具体的执行中,每一个数组的元素都会执行指定的方法,如果满足要求返回true,并会被存放在结果集中,不符合的则被剔除,最终返回的集合,即是结果判断后想要的集合。
以上代码执行结果为:
那么Predicate
从微软源码中可以看出Predicate
参考文章:
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~