c#委托的理解,c#委托的本质是什么
试想一下,如果我们为烹饪写一个厨师的烹饪方法,包括取菜、切菜、配菜、烹饪四个步骤,但是写这个方法代码的人希望配菜由方法的调用者来实现。换句话说,他希望在调用方法时将代码作为参数接收,并在方法中执行传入的代码。
但是,如何为一个方法传入代码呢?当然,大家都想到了通过接口的方式来实现。先不讨论接口,因为微软已经给我们提供了一个叫[delegate]的类型。
(1)委托依据:
1.先看代码:
(1).设置一个方法:void say hi(string name){ console . writeline(" hi ~ " name "!");}
(2).声明一种委托类型:Delegate Void DGSayhi(String Uname);
(3).创建委托类型对象:DGSayHi DG obj=new DGSayHi(SayHi);//方法在构造函数中传递
(4).委托的执行:
DG obj(" James Zou ");
//调用委托(奇怪:括号内调用对象?稍后解释。)
输出:Hi~JamesZou!
2.什么是委托?
(1)概念:“C#
中的委托类似于C或C。
函数指针在。使用委托允许程序员在委托对象中封装方法引用。那么调用delegate对象就可以执行delegate对象中方法引用所指向的方法,而不需要知道编译时会调用哪个方法(比如参数为delegate type的方法,它提供了一种机制来指定程序回调的方法)。" -
引自MSDN
(2) Popular:是一个调用列表,可以存储很多方法的指针(但是方法签名必须和委托类型签名相同)。只要调用这个列表,列表中所有指针对应的方法就会依次执行。
(3)举个例子:有A、C、d三台机器,点击一个红色按钮,它就会运行。操作员接到电话后被指示打开广告机,然后工作人员在接到电话后打开广告机。(在本例中
三机是方法,操作员可视为“委托”)
(4)轮廓图例:
DGSayHi dgObj=new
DGSayHi(萨伊希);
dgObj("詹姆斯");
//调用委托对象时,会执行委托对象中的方法。
3.委托有什么用?
A.可以帮助程序员在需要的时候根据条件动态执行多个方法:(前面例子的代码)
(1)设置三种方法:
void SayHi(字符串
名称){控制台。WriteLine("嗨~ "名);}
空的
大昭湖(串名){
控制台。WriteLine("你好~ "名);}
线
OHaUo(字符串名){ Console。WriteLine(" oh ahuo ~ "
姓名);返回“JapHi”;}
(2)创建委托类型对象,并通过向构造函数传递参数来向委托对象“注册”第一个方法:
DGSayHi dgObj=new
DGSayHi(萨伊希);
(3)继续“注册两种方法”:
dgObj
=大昭湖;//(奇怪:对象是用=符号操作的?稍后解释)
//dgObj
=oh ahuo;//注释这一行代码,因为编译时报错,OhaUo方法的签名和委托类型的签名不一致(委托签名没有返回值)。
(4)执行委托对象:
dgObj("詹姆斯");//执行了在此委托中注册的两个方法。
输出:
嗨~詹姆斯
你好~詹姆斯
(5)轮廓图例
作为委托方法参数(回调方法机制)
(1).连接上一个示例中的代码,然后定义一个方法:
void DoTestDelegateFun(DGSayHi
DgObj){dgObj(“钢铁侠”);}
(2).调用此方法:
DoTestDelegateFun(say hi);//Output: Hi~钢铁侠(奇怪:居然直接传方法?稍后解释)
C.委托语法糖
(1).注意,上面有3个地方我们都觉得“奇怪”:
A.调用委托对象DG obj(“James Zou”);
B.向委员会登记方法
dgObj=大昭湖;
c .将方法作为参数
DoTestDelegateFun(say hi);
这些用法实际上是FW提供的简单语法(它们有一个可爱的名字:syntax sugar),在编译时被编译器转换成完整的代码:
a.
dgObj。invoke(" JamesZou ");
b.dgObj=(DGSayHi)
委派。Combine(dgObj,new DGSayHi(这个。大昭湖));
//Combine方法将第二个参数添加到dgObj,并返回委托对象。
c.这个。DoTestDelegateFun(新DGSayHi(这个。say hi));
委托类、调用方法、组合方法从何而来?
(2)委托原则
1.delegate关键字
(1).概念:delegate关键字用于声明引用类型,引用类型可用于封装命名方法或匿名方法。
(2)编译后生成的中间代码。
请考虑一下。关键字是类型吗?没有,编译器遇到这个关键字做了什么?在[IL反汇编器]的帮助下,我们来看看:
A.开始-程序-如图所示:
B.打开项目文件夹下的bin\Debug文件夹,并找到该程序集。
CodeForFun.exe,拖动到【IL反汇编器】界面,可以看到汇编的IL代码:
我们找到了定义委托DGSayHi的DelegateForFun类,并在其中找到了委托类型声明代码。
编译前:delegatestringgsayhi(string
uName);
进入一个班级:
点开之后我们来看看:
你看到了什么?
(一)。继承了系统。中多重委托
。包含构造方法、BeginInvoke、EndInvoke和Invoke方法。
也就是说,此时,委托代码已经编译成如下代码:
编译后:
classDGSayHi:系统。中多重委托
{
公众的
DelegateForFun();
void Invoke(字符串值);
IAsyncResult BeginInvoke(字符串值,AsyncCallback回调,对象
对象);
void EndInvoke(IAsyncResult结果);
(3)系统。多播委托类
让我们借助来看看类库中的MulticastDelegate类。网络反射器工具。
public abstract class multicast Delegate:委托
由此可以看出继承关系:DGSayHi
组播代表代表
MulticastDelegate类中有三个重要成员,其中两个继承自
委托人:
A.三者的作用:
方法指针存储在_methodPtr中。
_target用于保存方法所在的对象。
_invocationList在使用时实际上是一个对象数组。当注册多个方法时,其他方法保存在该成员中,它也是委托链的关键容器。
B.外形图:
图中的委托对象dgObj在创建时会创建一个指向方法。
SayHi的指针并保存在_methodPtr中;_target持有SayHi方法所在类的对象(比如我在表单中按钮的click方法中写了这段代码,那么此时
_target是SayHi方法所在的form对象);_invocationList保存指向另外两个方法的指针,但是这两个方法指针安装在
在MuticastDelegate对象中。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。