Analyze the differences and connections between delegates, events, Func, Action, and Predicate in C# through IL

黄舟
Release: 2017-02-17 11:02:14
Original
1514 people have browsed it

I have always been confused about events and delegation, and I am not very good at using them. After taking some time to summarize it, I feel a lot clearer.

Let me first talk about the conclusion of my personal understanding:

delegate is a type in C# , which is actually a class that can hold a reference to a method.

There is no essential difference between variables declared by delegate and events declared by delegate. Events are packaged on the basis of variables declared by delegate, similar to The relationship between variables and attributes (you can see in the IL code that each event declared by a delegate corresponds to a variable declared by a private delegate) improves security.

Action and Func: These two are actually the Delegate defined by the system. It has many overloaded methods to facilitate various application situations. transfer. It is under the System namespace of the system and is therefore globally visible.

First of all, let’s understand the meaning of the icons in ILDasm:

This picture comes from: http://www.php.cn/

Delegate creation steps:

1. Use delegate The keyword creates a delegate, including declaring the return value and parameter type
2. Receive the delegate where used
3. Create an instance of the delegate and specify a method whose return value matches the parameter type to pass it


##1. Events and Delegation



Create a new event delegation test project: EventDelegateTest

The specific code is as follows:

<span style="font-size:14px;"><span style="font-size:14px;">namespace EventDelegateTest
{
    public class TestClass
    {
        public delegate int delegateAction();
        public event delegateAction OnActionEvent;
        public delegateAction daNew;
    }
}</span></span>
Copy after login

After compiling the code, use the ILDASM.EXE that comes with Visual Studio 2010:



Open the dll and you can see the following information:



From the above picture we can see the following information:

1. Delegation public delegate int delegateAction();

exists in the form of a class (delegateAction) in IL

. NET defines a delegate as a sealed class, derived from the base class System.MulticastDelegate, and inherits the three methods of the base class


2. public event delegateAction OnActionEvent;

In IL, it not only corresponds to event OnActionEvent but also corresponds to a field OnActionEvent;

The field daNew generated by field OnActionEvent and public delegateAction daNew is the same


##



都是以字段(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个参数)并且不返回值。

具体形式如下:http://www.php.cn/(v=vs.110).aspx


Func 委托:封装一个具有参数(0到16个参数)并返回 TResult 参数指定的类型值的方法。

具体形式如下:http://www.php.cn/(v=vs.110).aspx


那么这Action与Func是怎么实现的呢?

1、Action(以Action 委托:封装一个方法,该方法具有两个参数并且不返回值为例)

从微软公布的源码中,可以看到,如下实现:


public Action<bool,bool>  ac;
Copy after login

上面这个声明就是:该方法具有两个参数并且不返回值的委托。


其余使用方式与委托变量一样。

2、Func(以Func 委托:封装一个具有两个参数并返回 TResult 参数指定的类型值的方法为例)
从微软公布的源码中,可以看到,如下实现:



此处,可以看出Func与Action是类似的,唯一的区别就是,Func必须指定返回值的类型,使用方式与委托咱们自己使用委托变量是一样的,直接使用相应参数的Func或者Action声明变量,=或者+=挂载函数(方法即可)

这两个其实说白了就是系统定义好的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<int> myPredicate;
        int[] myNum = new int[8] { 12, 33, 89, 21, 15, 29, 40, 52 };
        public int[] myResult;
        public Form2()
        {
            InitializeComponent();
            myPredicate = delegate(int curNum)             
            {
                if (curNum % 2 == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            };
        }
        private void Form2_Load(object sender, EventArgs e)
        {
            myResult = Array.FindAll(myNum, myPredicate);
        }          
    }
}
Copy after login

上例中说明了Predicate的使用,FindAll方法中,参数2即是一个Predicate,在具体的执行中,每一个数组的元素都会执行指定的方法,如果满足要求返回true,并会被存放在结果集中,不符合的则被剔除,最终返回的集合,即是结果判断后想要的集合。
Array.FindAll 泛型方法:点击打开链接


以上代码执行结果为:


那么Predicate与委托又有什么关系呢?


从微软源码中可以看出Predicate是返回bool型的泛型委托,从本质上来说与Func、Action、事件、委托变量并无本质区别。




 以上就是通过IL分析C#中的委托、事件、Func、Action、Predicate之间的区别与联系的内容,更多相关内容请关注PHP中文网(www.php.cn)!



Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!