委托和事件
- 格式:pptx
- 大小:1.83 MB
- 文档页数:36
委托和事件的区别委托的本质,是⼀个类,⽽事件,是⼀个委托类型的私有变量加上两个公有⽅法(事件的+=和-=),这是本质区别。
打个⽐⽅,string 也是⼀个类,⽽string s = "a",这个s是string类型的⼀个变量(略有不恰当,为了⽅便直观理解)。
public delegate void myDel();相当于你创建了⼀个myDel的类,所以委托可以在任何地⽅创建,类需要实例化,所以委托需要实例化,要myDel m = ……;申明⼀个事件 public event myDel myEvent;事件myEvent是⼀个myDel类型的⼀个变量,因为是变量,所以事件只能在类⾥⾯申明,不需要实例化,有点类似与上⾯的那个m,当然不全是,他还有两e79fa5e98193e4b893e5b19e31333366306531个⽅法(+=,-=),调⽤⼀次+=⽅法,myEvent += MethodA;其实是把MethodA⽅法,封装成⼀个myDel类型的委托对象,然后把这个对象的引⽤赋值给这个myEvent变量。
如果多次调⽤+=,就是多个⽅法封装成了多个myDel委托对象,然后这些委托对象放在⼀个列表⾥⾯,然后myEvent就指向这个列表,触发的时候,就是调⽤这个列表⾥⾯的所有委托的Invoke⽅法。
转delegate是C#中的⼀种类型,它实际上是⼀个能够持有对某个⽅法的引⽤的类。
与其它的类不同,delegate类能够拥有⼀个签名(signature),并且它"只能持有与它的签名相匹配的⽅法的引⽤"。
它所实现的功能与C/C++中的函数指针⼗分相似。
它允许你传递⼀个类A的⽅法m给另⼀个类B的对象,使得类B的对象能够调⽤这个⽅法m。
但与函数指针相⽐,delegate有许多函数委托和事件在 .Net Framework中的应⽤⾮常⼴泛指针不具备的优点。
⾸先,函数指针只能指向静态函数,⽽delegate既可以引⽤静态函数,⼜可以引⽤⾮静态成员函数。
C#基础知识学习之✨委托(delegate)与事件(event)之间的介绍委托(delegate) 与事件(event)前言在之前的文章里介绍了C#中的委托(delegate)(Action、Func、Predicate)的基本含义及用法那本篇文章在这里还要介绍一个跟委托有很大关系的小伙伴——C#中的事件(event)事件跟委托是有很大联系的,所以也就导致很容易分不清他们两个,以及什么时候用这两个上面有博客提到委托,想单独了解委托的可以去看一下,本篇文章主要说一下什么是事件以及事件与委托的区别委托和事件的定义委托在这里再说一遍委托跟事件的简单定义(没有搜到特别准确的,都是大概定义,理解万岁)委托:delegate 是一种可用于封装命名或匿名方法的引用类型。
委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。
委托是一种动态调用方法的类型,属于引用型。
委托是对方法的抽象和封装。
委托对象实质上代表了方法的引用(即内存地址)委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以把多个方法链接在一起。
这样,在事件触发时可同时启动多个事件处理程序。
委托签名不需要与方法精确匹配。
事件事件:事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。
如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。
事件表示C#中已定义的一个对象,即处理通知过程的对象通常,每个事件的发生都会产生发送方和接收方。
在.net框架中,事件是将事件发送者(触发事件的对象)与事件接受者(处理事件的方法)相关联的一种代理类,即事件机制是通过代理类来实现的。
当一个事件被触发时,由该事件的代理来通知(调用)处理该事件的相应方法委托和事件的区别简单说了一下两者的定义,眼神好的小伙伴这时候就会发现,事件的说明里有提到一句话:“事件也可以算一种特殊的委托”,这句话不是特别准确,但是也不妨可以这样理解。
游戏开发第五章接口,委托与目录 CONTENTS五.一接口零一五.二委托零二五.三零三内容简述"接口"理解为就是定义一套标准,然后由实现类来具体实现其地方法,接口就是一组类地抽象。
"委托"理解为"方法地抽象",也就是说定义一个方法地模板,至于这个方法具体是怎么样地,就由方法自己去实现。
是用户操作,例如:按键,点击,鼠标移动等。
或者某些,例如:系统生成地通知。
应用程序需求响应发生时。
五.一接口接口(interface)是C#地一种数据类型,属于引用类型。
一个接口定义一个协定。
接口可以包含方法,属,与索引器,接口本身不提供它所定义地成员地实现,接口只指定实现该接口地类或结构需要提供地成员。
实现某接口地类需要遵守该接口定义地协定,即需要提供接口成员地实现。
五.一.一 . 接口地定义一.定义接口是指定一组函数成员而不实现成员地引用类型,其它类型与接口可以继承接口。
二.特点通过接口可以实现多重继承,接口里面地方法都需求由外面接口实现去实现方法体,那么其修饰符必然是public。
接口成员不能有new,static,abstract,override,virtual修饰符。
接口只包含成员地签名,接口没有构造函数,所有不能直接使用new对接口行实例化。
C#是单继承,接口是解决C#里面类可以同时继承多个基类地问题。
五.一.二接口地使用接口地声明在C#,声明接口使用interface关键字,一般形式如下:[访问修饰符] interface 接口名[ : 基接口列表]{//接口成员}说明:接口成员可以是属,方法,索引器与,不能包含字段,构造函数等。
所有接口成员隐式地具有了public访问修饰符,因此,接口成员不能添加任何访问修饰符。
接口主要用来定义一个规则,让企业内部或行业内部地软件开发员按标准去实现应用程序地功能。
因此,继承接口地类或结构需要实现接口地所有属,方法,索引器与,继承接口地方法与继承类相似 接口地继承接口也可以继承其它接口,而接口可以多继承,即接口可以从多个接口继承,基接口名之间用逗号分隔。
委托和事件的区别(讲的很详细)--转委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。
它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。
本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。
将方法作为方法的参数我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:public void GreetPeople(string name) {// 做某些额外的事情,比如初始化之类,此处略EnglishGreeting(name);}public void EnglishGreeting(string name) {Console.WriteLine("Morning, " + name);}暂且不管这两个方法有没有什么实际意义。
GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“Jimmy”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出“Morning, Jimmy”。
现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:public void ChineseGreeting(string name){Console.WriteLine("早上好, " + name);}这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:public enum Language{English, Chinese}public void GreetPeople(string name, Language lang){//做某些额外的事情,比如初始化之类,此处略swith(lang){case Language.English:EnglishGreeting(name);break;case Language.Chinese:ChineseGreeting(name);break;}}OK,尽管这样解决了问题,但我不说大家也很容易想到,这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。
委托、事件和回调函数这3者之间到底是什么关系
简⽽⾔之,回调函数就是⼀个通过函数指针调⽤的函数。
如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤为调⽤它所指向的函数时,我们就说这是回调函数。
为什么要使⽤回调函数?
因为可以把调⽤者与被调⽤者分开。
调⽤者不关⼼谁是被调⽤者,所有它需知道的,只是存在⼀个具有某种特定原型、某些限制条件(如返回值为int)的被调⽤函数。
回调函数:就是指向指针的指针,保存的就⼀个地址,通常⽤在钩⼦过程,异步过程调⽤等等,因为是⼀个地址,不会携带任何其他的信息所以⼀般的回调函数不是类型安全的.
委托就⼀个类,他的每个实例就是对⼀个⽅法(定义好了返回值,输⼊参数类型,个数以及函数调⽤的约定)和其调⽤时操作的对象的⼀个封装. c#中的事件是依靠委托来实现的,事件就是⼀种通知机制,当⼀件事情发⽣时(⽐如说状态改变)通知给相关的其他对象.。
初学者在理解委托和事件时常常被msdn搞糊涂,为了让初学.net的人快速应用.net的委托和事件模型编程,我在这里主要是提出理解的关键,以下代码都可直接运行,先看下面的代码。
using System;namespace delegeteTest{class delegeteClass{public delegate void fHandler(int a); //关键-此行可以看成类的声明public fHandler f0;public void d(int a,int b ){int c=a+b;f0(c);}}class test{public void output(int mun){System.Console .WriteLine ("{0}",mun);}[STAThread]static void Main(string[] args){test t=new test ();delegeteClass dc=new delegeteClass ();dc.f0 =new delegeteTest.delegeteClass.fHandler (t.ou tput);//实例的初始化dc.d(2,3);}}}解释一下"关键": 实际上 public delegate void fHandler(int a);可以看成如下:class fHandler{.....}类内部由编译器自动完成,是一个sealed类通过反汇编可以看到,是一个类的声明,它检查加入自己的函数的信息,如,返回值和参数类型现在熟悉vc++的人可能感觉到public delegate void fHandler(int a);这句就象一个宏现在好了既然是个类的定义,那么也可以直接拿到命名空间下了using System;namespace delegeteTest{public delegate void fHandler(int a);//fHandler现在上升到了类的层次class delegeteClass{public fHandler f0;//声明了委托fHandler的实例f0;public fHandler f1;//也可以再声明一个fHandler类的实例f1;public void d(int a,int b ){int c=a+b;f0(c);}}class test{public void output(int mun){System.Console .WriteLine ("{0}",mun);}[STAThread]static void Main(string[] args){test t=new test ();delegeteClass dc=new delegeteClass ();dc.f0 =new delegeteTest.fHandler (t.output);//此行做相应的修改dc.d(2,3);}}}有以上可知public delegate void fHandler(int a)这行代码只能放在能够声明类的地方,自然fHandler.后面的函数都是静态方法了,如fHandler.Equals (...);那么fHandler到底声明了什么? 实际上是声明了函数的类型,既函数的有关信息(如返回值,参数类型)。
什么是委托?什么是事件?事件与委托的区别?什么是委托?委托是种:引⽤⽅法的对象。
此对象可以将指针指向引⽤的⽅法,也可以说对象(委托)将消息发给订阅者(⽅法)什么是事件?事件与委托的区别?事件是种:特殊的委托区别:事件是解决委托的两个缺陷1、不⼩⼼取消掉订阅者 (封装订阅)委托允许使⽤ +=和= 两种运算符,就会导致不⼩⼼取消掉订阅者,⽽事件不允许使⽤=2、包容类外也可以(发布)通知 (封装发布)事件确保只有包容类才能触发⼀个事件通知 [不允许类的外部执⾏事件通知] (事件只能在定义的类中调⽤(发布))换⾔之,事件提供了必要的封装来防⽌任何外部类发布⼀个事件或者取消之前的订阅者。
这样,就完美的解决了普通委托存在的两个问题PS: 参考《C#本质论》事件就是要解决下列代码中:+=和= ,在外部类中发布委托的问题public class Cooler{public Cooler(int temperature){this.Temperature = temperature;}public int Temperature { get; set; }public void OnTemperaTureChanged(int tem){if (tem > Temperature){Console.WriteLine($"Cooler On");}else{Console.WriteLine($"Cooler Off");}}}public class Heater{public Heater(int temperature){this.Temperature = temperature;}public int Temperature { get; set; }public void OnTemperaTureChanged(int tem){if (tem < Temperature){Console.WriteLine($"Heater On");}else{Console.WriteLine($"Heater Off");}}}class委托or事件{//声明委托// public delegate string delegateHandle(object sender, HandleEventArgs args);////声明事件//public event delegateHandle eventHandle;////已发事件的⽅法//public void Method(HandleEventArgs args)//{// if (eventHandle != null)// {// eventHandle(this, args);// }//}public delegate void delegateHandle(int tem);private delegateHandle _OndelegateHandleChanged;public delegateHandle OndelegateHandleChanged{get { return _OndelegateHandleChanged; }set { _OndelegateHandleChanged = value; }}private int temperature;public int Temperature{get { return temperature; }set { temperature = value; if(OndelegateHandleChanged!=null)OndelegateHandleChanged(value); } }}static void Main(string[] args){委托or事件 or = new委托or事件();Cooler cooler = new Cooler(80);Heater heater = new Heater(60);//or.eventHandle += Or_eventHandle;//or.Method(handler);or.OndelegateHandleChanged += cooler.OnTemperaTureChanged;or.OndelegateHandleChanged += heater.OnTemperaTureChanged;or.OndelegateHandleChanged = heater.OnTemperaTureChanged;or.OndelegateHandleChanged(45);Console.ReadLine();}View Code。
<五> 委托与事件1、委托C#的委托相当于C/C++中的函数指针,函数指针用指针获取一个函数的入口地址,实现对函数的操作。
委托是面向对象的,是引用类型,因此对委托的使用要先定义后实例化,最后才调用。
委托与C/C++有本质的区别:C/C++中的函数指针仅仅是一个内存地址,其中不包含任何有关函数的参数、返回值以及调用约定等方面的信息。
2、声明委托C#使用关键字delegate声明委托类型。
格式如下:[修饰符] delegate 结果类型委托名称([形式参数列表]);◆访问修饰符为可选项,可以使用new、public、private、protected和internal之一。
◆结果类型指委托对应方法的返回值的类型。
◆形式参数列表指定委托对应方法的参数。
注意,如果参数是一个指针,则必须用unsafe修饰符声明委托。
3、委托的实现在C#中,可以通过以下三个步骤定义和使用委托:声明、建立委托实例、实例化和调用。
上面已经介绍了如何声明一个委托,下面介绍后两个步骤,即建立委托实例、实例化和调用。
delegate语句定义委托的参数类型(形式参数列表的参数类型)和返回值类型(结果类型),任何具有匹配参数类型和返回值类型的方法均可用来建立此委托的实例。
因此,声明了一个委托后,为了实现这个委托,可以按如下的步骤操作:(1)建立委托实例:委托实例是委托所要调用的方法,它与声明的委托在以下三个方面必须相同。
◆方法类型。
如果委托被声明的为void(无返回值)结果类型,则委托实例(方法)必须是void类型;如果委托声明的是其它结果类型(如int类型),则委托实例(方法)返回值类型必须与之对应。
◆参数类型。
委托声明的参数列表类型必须与委托实例(方法)的参数列表类型相同。
◆参数个数。
委托声明的参数列表个数必须与委托实例(方法)的参数列表个数相同。
除上述三个方面外,其他方面,例如实例与委托的名称、参数名称不必相同。
只要这三个方面相同,就可以作为一个委托的实例过程。
委托与事件委托的应用:将方法作为另一个方法的参数view plaincopy to clipboardprint?1. using System;2. using System.Collections.Generic;3. using System.Text;4. namespace Delegate {5. //定义委托,它定义了可以代表的方法的类型6. public delegate void GreetingDelegate(string name);7. class Program {8. private static void EnglishGreeting(string name) {9. Console.WriteLine(”Morning, ” + name);10. } Www~11. private static void ChineseGreeting(string name) {12. Console.WriteLine(”早上好, ” + name);13. }14. //注意此方法,它接受一个GreetingDelegate类型的方法作为参数15. private static void GreetPeople(string name, GreetingDelegateMakeGreeting) {16. MakeGreeting(name);17. }18. static void Main(string[] args) {19. GreetPeople(”Jimmy Zhang”, EnglishGreeting);20. GreetPeople(”张子阳”, ChineseGreeting);21. Console.ReadKey();22. }23. }24. }1.委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。