백엔드 개발 C#.Net 튜토리얼 IL을 통해 C#의 대리자, 이벤트, Func, Action 및 Predicate 간의 차이점과 연결을 분석합니다.

IL을 통해 C#의 대리자, 이벤트, Func, Action 및 Predicate 간의 차이점과 연결을 분석합니다.

Feb 17, 2017 am 11:02 AM

저는 항상 이벤트와 위임에 대해 헷갈리고 잘 활용하지 못합니다. 잠시 시간을 내어 요약해 본 후에는 훨씬 더 명확해진 느낌이 들었습니다.

먼저 개인적인 이해에 대해 이야기하겠습니다.

Delegate는 C#의 유형입니다. 실제로 메소드에 대한 참조를 보유할 수 있는 클래스입니다.

델리게이트가 선언한 변수와 델리게이트가 선언한 이벤트는 본질적인 차이가 없습니다. 이벤트는 델리게이트가 선언한 변수를 기준으로 패키징됩니다. 변수와 속성 사이(대리자가 선언한 각 이벤트가 개인 대리자가 선언한 변수에 해당함을 IL 코드에서 볼 수 있음)는 보안을 향상시킵니다.

Action 및 Func: 이 두 가지는 실제로 시스템에서 정의한 Delegate입니다. 다양한 애플리케이션 호출을 용이하게 하기 위해 많은 오버로드된 메서드가 있습니다. 이는 시스템의 System 네임스페이스 아래에 있으므로 전역적으로 표시됩니다.

먼저 ILDasm의 아이콘 의미를 이해해 보겠습니다.

이 사진 출처: http://www.php.cn/

위임 생성 단계:

1. 대리자 사용 키워드는 반환 값 및 매개 변수 유형 선언을 포함하여 대리자를 생성합니다
2. 사용된 대리자를 수신합니다
3. 이 대리자의 인스턴스를 만들고 반환 값이 일치하는 메서드를 지정합니다. 매개변수 유형을 입력하고 거기에 전달하세요


1.



새 이벤트 위임 테스트 프로젝트 만들기: EventDelegateTest

구체적인 코드는 다음과 같습니다.

<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>
로그인 후 복사

코드 컴파일 후 Visual과 함께 제공되는 ILDASM.EXE를 사용하세요. Studio 2010:



dll을 열면 다음을 볼 수 있습니다. 다음 정보:




위 그림에서 우리는 다음 정보를 볼 수 있습니다:

1. Delegation Public Delegate int DelegateAction();

은 클래스(delegateAction) 형태로 존재합니다. IL

.NET에서는 대리자를 기본 클래스 System.MulticastDelegate에서 파생된 봉인된 클래스로 정의하고 기본 클래스

<🎜의 세 가지 메서드를 상속합니다. >


2. 공개 이벤트 DelegateAction OnActionEvent;

IL에서는 이벤트에만 해당하는 것이 아닙니다. OnActionEvent는 OnActionEvent 필드에도 해당합니다.

OnActionEvent 필드와 public DelegateAction daNew에 의해 생성된 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个参数)并且不返回值。

具体形式如下: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;
로그인 후 복사

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


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

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);
        }          
    }
}
로그인 후 복사

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


以上代码执行结果为:


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


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




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



본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C 언어로 Null의 대안은 무엇입니까? C 언어로 Null의 대안은 무엇입니까? Mar 03, 2025 pm 05:37 PM

이 기사는 C의 Null 포인터 단축의 도전에 대해 탐구합니다. 그것은 문제가 그 자체가 아니라 오용한다고 주장합니다. 이 기사는 사전 수준 점검, 포인터 이니셜을 포함한 수반을 방지하기위한 모범 사례에 대해 자세히 설명합니다.

차세대 C 컴파일러를 추가하는 방법 차세대 C 컴파일러를 추가하는 방법 Mar 03, 2025 pm 05:44 PM

이 기사에서는 printf 내에서 \ n 탈출 시퀀스를 사용하여 C에서 Newline 문자를 만드는 방법을 설명하고 함수를 넣습니다. 기능을 자세히 설명하고 출력에서 ​​라인 브레이크 사용을 보여주는 코드 예제를 제공합니다.

어떤 C 언어 컴파일러가 더 낫습니까? 어떤 C 언어 컴파일러가 더 낫습니까? Mar 03, 2025 pm 05:39 PM

이 기사는 초보자가 C 컴파일러를 선택하도록 안내합니다. GCC는 사용 편의성, 광범위한 가용성 및 광범위한 리소스로 인해 초보자에게 가장 적합하다고 주장합니다. 그러나 GCC, Clang, MSVC 및 TCC도 비교하여 차이를 강조합니다.

Null은 C 언어로 된 현대 프로그래밍에서 여전히 중요합니까? Null은 C 언어로 된 현대 프로그래밍에서 여전히 중요합니까? Mar 03, 2025 pm 05:35 PM

이 기사는 현대 C 프로그래밍에서 NULL의 지속적인 중요성을 강조합니다. 발전에도 불구하고 NULL은 명시적인 포인터 관리에 중요하며, 유효한 메모리 주소가 없음을 표시하여 세분화 결함을 방지합니다. 최고의 PRAC

C 언어 컴파일러의 웹 버전은 무엇입니까? C 언어 컴파일러의 웹 버전은 무엇입니까? Mar 03, 2025 pm 05:42 PM

이 기사에서는 초보자를위한 온라인 C 컴파일러를 검토하여 사용 편의성 및 디버깅 기능에 중점을 둡니다. OnlineGDB 및 Repl.it는 사용자 친화적 인 인터페이스 및 유용한 디버깅 도구를 위해 강조 표시됩니다. 프로그램 및 컴파일과 같은 다른 옵션

C 언어 온라인 프로그래밍 웹 사이트 C 언어 컴파일러 공식 웹 사이트 요약 C 언어 온라인 프로그래밍 웹 사이트 C 언어 컴파일러 공식 웹 사이트 요약 Mar 03, 2025 pm 05:41 PM

이 기사는 온라인 C 프로그래밍 플랫폼을 비교하여 디버깅 도구, IDE 기능, 표준 컴플라이언스 및 메모리/실행 제한과 같은 기능의 차이점을 강조합니다. "최고의"플랫폼은 사용자의 요구에 달려 있다고 주장합니다.

C 언어 컴파일러에 의해 코드를 복사하는 방법 C 언어 컴파일러에 의해 코드를 복사하는 방법 Mar 03, 2025 pm 05:43 PM

이 기사에서는 C IDE의 효율적인 코드 복사에 대해 설명합니다. 복사는 컴파일러 기능이 아닌 IDE 기능이며 IDE 선택 도구 사용, 코드 폴딩, 검색/교체, Templa를 포함하여 효율성 향상을위한 세부 사항 전략을 강조합니다.

C 언어 컴파일러에 의해 출력 창을 팝업하지 않는 문제를 해결하는 방법 C 언어 컴파일러에 의해 출력 창을 팝업하지 않는 문제를 해결하는 방법 Mar 03, 2025 pm 05:40 PM

이 기사는 C 프로그램 컴파일에서 누락 된 출력 창을 문제 해결합니다. 실행 가능, 프로그램 오류, 잘못된 컴파일러 설정, 백그라운드 프로세스 및 빠른 프로그램 종료와 같은 원인을 검사합니다. 솔루션은 ch

See all articles