C#中的委托(Delegate)和事件(Event)-例子解释

C#中的委托(Delegate)和事件(Event)-例子解释
C#中的委托(Delegate)和事件(Event)-例子解释

https://www.360docs.net/doc/ce10003423.html,/uid-576762-id-2733751.html

C#中的委托(Delegate)和事件(Event)2007-11-30 11:40:00

分类:

把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式——观察者(Observer)有一个参考。

委托和事件应该是C#相较于C++等之前的非托管的语言提出的一个新的术语(term)。“旧瓶装新酒”这样的描述似乎有些“贬义”,但确实是这样。委托也好,事件也好最初的起源是C/C++中的函数指针,关于函数指针的简单介绍可以参见我以前的一篇《C/C++中指向函数的指针》。不过旧瓶装新酒没有什么不好,反而给人添加了许多新滋味。

1. Function pointer--the origin of delegates and events .

书回正传,既然函数指针是它们(委托和事件)的起源。那我们先看看什么情况下我们需要函数指针。函数指针最常用的方式就是回调(callback)——在函数休内回调主函数里的函数。有些绕口,看代码:

//Platform: WinXP + VC6.0

#include

#include

using namespace std;

void max(int a,int b)

{

cout<<"now call max("<

int t =a>b?a:b;

cout<

}

void min(int a,int b)

{

cout<<"now call min("<

int t =a

cout<

}

2,Introduce delegate in c#;

.net里一向是"忌讳"提及"指针"的,"指针"很多程度上意味着不安全。

C#.net里便提出了一个新的术语:委托(delegate)来实现类似函数指针的功能。我们来看看在C#中怎么样实现上面的例子。

//Platform: WinXP + C# in vs2003

using System;

namespace Class1

{

class ExcelProgram

{

static void max(int a,int b)

{

Console.WriteLine("now call

max({0},{1})",a,b);

int t =a>b?a:b;

Console.WriteLine(t);

}

static void min(int a,int b)

{

Console.WriteLine("now call

min({0},{1})",a,b);

int t =a

Console.WriteLine(t);

}

delegate void myFun(int a,int b);//定义

一个委托用来引用max,min

//回调函数

static void callback(myFun

fun,int a,int b)

{

fun(a,b);

}

[STAThread]

static void Main(string[]args)

{

int i =10;

int j =55;

callback(new myFun(max),i,j);

callback(new myFun(min),i,j);

Console.ReadLine();

}

}

}

其实代码上大同小异,除了几个static申明以外(C#除静态成员外必须要求对象引用),最大的变化要算定义"函数指指",哦...不..不..不..应该是定义"委托"(小样穿上马甲了..). 定义委托的语法如下:

delegate void myFun(int a, int b); //定义一个委托用来引用max,min

其中delegate是关键字,myFun是委托名,剩下的是函数签名(signature).我们可以申明一个委托:

myFun Max = new myFun(max);

那么上面的回调函数的代码便可以写成:callback(Max,i,j);

3, Difference between function pointer and delegate;

委托除了可以引用一个函数外,能力上还有了一些加强,其中有一点不得不提的是:多点委托(Multicast delegate).简单地讲就是可以通过一个申明一个委托,来调用多个函数,不信?我们只要稍微更改一下上面的C#代码中的Main 函数就可以了,类似:

static void Main(string[] args)

{

int i = 10;

int j = 55;

myFun mulCast = new myFun(max);

mulCast +=new myFun(min); //(1)

callback(mulCast,i,j);

//callback(new myFun(min),i,j);

Console.ReadLine();

}

输出如下:

now call max(10,55)...

55

now call min(10,55)...

10

Press any key to continue

没骗你吧,我们只用了一个委托mulCast便同时调用了max和min。不知你注意到没有,上面代码的(1)处用"+="给已经存在的委托(mulCast)又加了一个函数(min)。这样看来C#中的委托更像一个函数指针链表。实质是在C#中,delegate 关键字指定的委托自动从System.MulticastDelegate派生.而

System.MulticastDelegate是一个带有链接的委托列表,在callback中只需调用mulCast的引用便可以以同样的参数调用该链表中的所有函数。

如果还是觉得不过隐,那我们就继续,下图展示了刚才那段C#代码的IL(用ILDasm反汇编即可):

在C#中委托是作为一个特殊的类型(Type,Object)来对待的,委托对象也有自己的成员:BeginInvoke,EndInvoke,Invoke。这几个成员是你定义一个委托时编译器帮你自动自成的,而且他们都是virtual函数,具体函数体由runtime来实现。我们双击一个callback,可以看见以下IL:

{

// 代码大小 9 (0x9)

.maxstack 8

IL_0000: ldarg.0

IL_0001: ldarg.1

IL_0002: ldarg.2

IL_0003: callvirt instance void

Class1.ExcelProgram/myFun::Invoke(int32,

int32)

IL_0008: ret

} // end of method ExcelProgram::callback

从这段IL我们可以看出,当我们使用语句:fun(a,b)时,调用的却是委托对象(即然委托是类型,那么他自也就会有对象)的myFun::Invoke().该委托对象(即上面的mulCast)通过调用Invoke来调用对象本身所关系的函数引用。

那我们再看看,一个委托对象是怎么样关联到函数的呢,我们双击Main函数,可以看到以下IL,虽然IL语法复杂但仍不影响我们了解它是怎么样将一个委托关联到一个(或多个)函数的引用的。

.method private hidebysig static void Main(string[] args) cil managed {

.entrypoint

.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )

// 代码大小 58 (0x3a)

.maxstack 4

.locals ([0] int32 i,

[1] int32 j,

[2]class Class1.ExcelProgram/myFun mulCast) IL_0000: ldc.i4.s 10

IL_0002: stloc.0

IL_0003: ldc.i4.s 55

IL_0005: stloc.1

IL_0006: ldnull

IL_0007: ldftn void Class1.ExcelProgram::max(int32,

int32)

IL_000d: newobj instance void

Class1.ExcelProgram/myFun::.ctor(object,

native int)

IL_0012: stloc.2

IL_0013: ldloc.2

IL_0014: ldnull

IL_0015: ldftn void Class1.ExcelProgram::min(int32,

int32)

IL_001b: newobj instance void

Class1.ExcelProgram/myFun::.ctor(object,

native int)

IL_0020: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,

class

[mscorlib]System.Delegate)

IL_0025: castclass Class1.ExcelProgram/myFun

IL_002a: stloc.2

IL_002b: ldloc.2

IL_002c: ldloc.0

IL_002d: ldloc.1

IL_002e: call void

Class1.ExcelProgram::callback(class Class1.ExcelProgram/myFun,

int32,

int32)

IL_0033: call string

[mscorlib]System.Console::ReadLine()

IL_0038: pop

IL_0039: ret

} // end of method ExcelProgram::Main

从上面的IL可以看出对于语句:

myFun mulCast = new myFun(max);

是通过以max作为参数构建一个委托对象mulCast。但对于语句:

mulCast += new myFun(min);

等价于(你甚至可以用下面的语句代码上面的:mulCast += new myFun(min)): mulCast = (myFun) https://www.360docs.net/doc/ce10003423.html,bine(mulCast, new myFun(min));

哦,原来是通过调用https://www.360docs.net/doc/ce10003423.html,bine的静态方法将mulCast和min函数进行关联,https://www.360docs.net/doc/ce10003423.html,bine方法只是简单地将min函数的引用加至委托对象mulCast的函数引用列表中。

4,Introduce event;

事件/消息机制是Windows的核心,其实提供事件功能的却是函数指针,你信么?接下来我们再看看C#事件(Event).在C#中事件是一类特殊的委托.

一个类提供了"事件",那么他至少提供了以下字段/方法:

一个委托类型的字段(field),用来保存一旦事件时通知哪些对象。即通知所有订阅该事件的对象.别忘记C#中委托是支持多播的。

两个方法,以委托类型为参数。作用是将订阅该事件的对象方法加至上面的委托类型字段中,以便事件发生后可以通过调用该方法来通知对象事件已发生。

我们简单地定义一个类Test,该类支持事件:

class Test

{

public event EventHandler OnClick;

public void GenEvent(EventArgs e) //引发事件方法

{

EventHandler temp = OnClick;

//通知所有已订阅事件的对象

if(temp != null)

temp(this,e);

}

}

我们反汇编这段代码,如下图:

简单地定义一个字段哪来的那么多方法?其实这都是编译器帮你加上去的。当你定义一个事件时,编译器为了实现事件的功能会自动加上两个方法来提供“订阅”和“取消订阅”的功能。

通过下面的语法,你便可以订阅事件:

test.OnClick +=new EventHandler(test_OnClick);

也就是说,一旦test事件发生时(通过调用test.GenEvent()方法)。test 便会调用注册到OnClick上的方法。来通知所有订阅该事件的对象。

订阅是什么?“订阅就是调用定义事件时自动生成的add_OnClick.”“那取消订阅就是调用定义事件时自动生成的remove_OnClick”,恭喜你!都学会抢答了.对于上面的订阅事件语句,逻辑意义上等同于:

test.add_OnClick(new EventHandler(test_OnClick));

但C#并不能直接调用该方法,只能通过 "+=" 来实现。来看IL:

IL_003b: ldftn void

Class1.ExcelProgram::test_OnClick(object,

class [mscorlib]System.EventArgs) //先将test_OnClick压栈

IL_0041: newobj instance void

[mscorlib]System.EventHandler::.ctor(object,

native int) //new一个委托对对象 IL_0046: callvirt instance void

Class1.ExcelProgram/Test::add_OnClick(class

[mscorlib]System.EventHandler) //通过调用add_OnClick方法将上面生委托加至test的事件(委托列表)中.

5,summarize.

如果对设计模式中的观察者模式较为熟悉的话。其实支持事件的类也就是观察者模式中的Subject(主题,我个人比较喜欢这么译).而所有订阅事件的对象构成了Observers.

最后来句总结吧,总结也许不严谨,但提供理解那还是绝佳滴..我骗你..(鼻子又变长了).....

"委托"是"函数指针"链表,当然该链表也可以只有一个元素,如果这样的话:"委托" 约等于"函数指针";

"事件"是一类特特殊的"委托",你定义一个"事件",表示你同时定义了:一个委托+两个方法。

后记:如果还不理解事件,先不要急,说不定你先把它忘记不想,等会一闪光,你就会理解了。或者你等着我下一篇《设计模式----观察者(Observer)》,我想等你看完设计模式中的观察者之后再回来看"事件",看"多播委托(MulticastDelegate)"应该可以:忽然开朗。

如果还觉得不过隐。下面给出一个很好的帮助理解的例子,来自Jeffrey Richter.希望我的注解能帮上些忙:

using System;

using System.Text;

using System.Data;

namespace Class1

{

//定义事件引发时,需要传的参数

class NewMailEventArgs:EventArgs

{

private readonly string m_from;

private readonly string m_to;

private readonly string m_subject;

public NewMailEventArgs(string from,string to,

string subject)

{

m_from =from;

m_to =to;

m_subject =subject;

}

public string From

{

get{return m_from;}

}

public string To

{

get{return m_to;}

}

public string Subject

{

get{return m_subject;}

}

}

//事件所用的委托(链表)

delegate void NewMailEventHandler(object sender,NewMai lEventArgs e);

//提供事件的类

class MailManager

{

public event NewMailEventHandler NewMail;

//通知已订阅事件的对象

protected virtual void OnNewMail(NewMailEventArg s e)

{

NewMailEventHandler

temp =NewMail;//MulticastDelegate一个委托链表

//通知所有已订阅事件的对象

if(temp !=null)

temp(this,e);//通过事件NewMail(一

种特殊的委托)逐一回调客户端的方法

}

//提供一个方法,引发事件

public void SimulateNewMail(string from,string to,string subject)

{

NewMailEventArgs

e =new NewMailEventArgs(from,to,subject);

OnNewMail(e);

}

}

//使用事件

class Fax

{

public Fax(MailManager mm)

{

//Subscribe

mm.NewMail +=new NewMailEventHandler(Fa x_NewMail);

}

private void Fax_NewMail(object sender,NewMail EventArgs e)

{

Console.WriteLine("Message arrived at Fax...");

Console.WriteLine("From={0}, To={1}, Subject='{2}'",e.From,e.To,e.Subject);

}

public void Unregister(MailManager mm)

{

mm.NewMail -=new NewMailEventHandler(Fa x_NewMail);

}

}

class Print

{

public Print(MailManager mm)

{

//Subscribe ,在mm.NewMail的委托链表中加入Print_NewMail方法

mm.NewMail +=new NewMailEventHandler(Pr int_NewMail);

}

private void Print_NewMail(object sender,NewMa ilEventArgs e)

{

Console.WriteLine("Message arrived at Print...");

Console.WriteLine("From={0}, To={1}, Subject='{2}'",e.From,e.To,e.Subject);

}

public void Unregister(MailManager mm)

{

mm.NewMail -=new NewMailEventHandler(Pr int_NewMail);

}

}

class ExcelProgram

{

[STAThread]

static void Main(string[]args)

{

MailManager mm =new MailManager();

if(true)

{

Fax fax =new Fax(mm);

Print prt =new Print(mm);

}

mm.SimulateNewMail("Anco","Jerry","Event test");

Console.ReadLine();

C#委托及事件

C#委托及事件 在C#中,委托(delegate)是一种引用类型,在其他语言中,与委托最接近的是函数指针,但委托不仅存储对方法入口点的引用,还存储对用于调用方法的对象实例的引用。 简单的讲委托(delegate)是一种类型安全的函数指针,首先,看下面的示例程序,在C++中使用函数指针。 首先,存在两个方法:分别用于求两个数的最大值和最小值。 int Max(int x,int y) { return x>yx:y; } int Min(int x,int y) { return x } 上面两个函数的特点是:函数的返回值类型及参数列表都一样。那么,我们可以使用函数指针来指代这两个函数,并且可以将具体的指代过程交给用户,这样,可以减少用户判断的次数。 下面我们可以建立一个函数指针,将指向任意一个方法,代码如下所示: 建立一个委托类型,并声明该委托可以指向的方法的签名(函数原型)delegate void MyDelegate(int a,int b); 2.建立一个委托类的实例,并指向要调用的方法 用委托类实例调用所指向的方法 int c=md(4,5); 下面通过实例来演示C#中委托的使用。

案例操作020601:利用委托实现方法的 动态调用 首先,添加如下控件: 两个RadioButton,分别用来让用户选 择求最大值以及求最小值 二个TextBox,用来输入两个操作数 一个TextBox,用来显示运算结果 一个Button,用来执行运算 界面如下图所示: 下一步,在窗口中添加两个方法:Max,Min,这两方法的代码如下: int Max(int x,int y) { return x>yx:y; } int Min(int x,int y) { return x } 窗口中的代码,如下图所示:

C#委托事件详解

C# 中的委托和事件 引言 委托和事件在 .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()方法,以适应新的需求。 在考虑新的解决方案之前,我们先看看 GreetPeople的方法签名:

唯一看明白额委托与事件讲解

一、在控制台下使用委托和事件 我们都知道,C#中有“接口”这个概念,所谓的“接口”就是定义一套标准,然后由实现类来具体实现其中的方法,所以说“接口,是一组类的抽象”。同样道理,我们可以将“委托”理解为“方法的抽象”,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。 我们知道接口的最大好处就是可以实现多态,同理,“委托”是可以实现方法的多态,当我们想调用某个具体方法的时候,我们不直接调用这个方法,而是去调用这个委托。当然,我们必须在具体方法和委托之间建立某种关联。 下面我们来看例子。 首先,我们定义一个委托: public delegate void SaySomething(string name); 这跟抽象方法的语法格式很相似,只是多了一个关键字delegate。既然是对方法的一种抽象,那么我们最关注的当然就是方法的返回值以及方法的参数了。所以上面红色的部分就是我们定义出来的一个规矩,如果某个方法想委托我去做事,那么请你遵循我的规矩,就是返回值为void,参数为一个字符串。我们这个委托的含义是,当某个人来了,就向他说点东西。 好,既然我们已经定义了这个规矩,下面我们就定义具体的方法了。 public void SayHello(string name) { Console.WriteLine("Hello," + name + "!"); } public void SayNiceToMeetYou(string name) { Console.WriteLine("Nice to meet you," + name + "!"); } 我们这里一共定义了两个方法,一个是向某人说Hello,另一个是向某人说Nice to meet you。我们看到,这里定义的两个方法的返回值和参数跟我们前面定义的“委托”是一致的。 接下来,我们来看事件。 public event SaySomething come;

委托事件1

委托 定义委托的语法和定义方法比较相似,只是比方法多了一个关键字delegate,我们都知道方法就是将类型参数化,所谓的类型参数化就是说该方法接受一个参数,而该参数是某种类型的参数,比如int、string等等;而委托是将方法参数化,说了上面的那个类型参数化之后,相信你也能猜到方法参数化的意思了,对,就是将方法作为一个参数传到一个委托中。 首先来看看声明委托的语句: public deletate void MyDelegate(); public:访问修饰符delegate:关键字void:返回类型MyDelegate:委托名称( ):参数列表 看到声明大家会想了,为什么该委托的返回值,参数列表要这样的,我不能返回一个string,一个int么?我不能给委托加几个参数么?答案是:当然可以,但委托的定义是相对于方法来说的,因为得你的委托最终是要来注册方法的,而你的方法是具有某种签名的,所以你要给怎样签名的方法来声明一个委托,该委托就要和该方法具有同等的签名,就类似于你用一个int 类型的变量去接受一个string类型的值,显然是不行的(个人理解).... * 委托只要定义就可以了,我们并不需要关心他的实现 委托的使用 注册委托有两种方法: 第一种:直接将方法赋值[=]或者用“+=”给一个委托==>委托名=[+=] 方法名 第二种:委托本质也是一个类,只是一个特殊的类,所以我们也可以实例化一个委托对象通过委托构造函数来注册委托==》委托名对象名= new 委托名(方法名)

了解了委托的声明和使用,我们就可以来看小例子来加深理解了 首先看看界面: 界面上就是简单的四个按钮两个属于委托,两个属于事件,都是一个用来执行,一个用来干扰,以便于来理解委托事件 然后看后台代码,首先我定义了一个Test类,声明委托,实例了委托,还声明了事件,写了个方法用来触发事件,代码如下: 1public class Test 2 { 3//声明一个委托 4public delegate void MyDelegate(); 5 6//创建一个委托实例 7public MyDelegate myDel; 8//声明一个事件 9public event MyDelegate EventMyDel; 10 11//事件触发机制(必须和事件在同一个类中) 外界无法直接用EventMyDel()来触发事件 12public void DoEventMyDel() 13 { 14 EventMyDel(); 15 } 16 }

委托与事件 机制

Button1.Click+=new EventHandler(Button1_Click);-----------------@1 大家都熟悉的一段代码,Button1.Click是事件(也可以说是一条委托链),EventHandler 是委托,Button1_Click是订阅事件的人,也可以说是委托的人。 通过这样的机制,一个事件可以有多个订阅者,从而可以实现点击button可以响应多个方法。委托,顾名思义,委托给别人。 事件,“发布者/订阅者” 模式,发布者发布一个事件,订阅者订阅这个事件,当事件触发时,就会通知订阅者。通知这个过程是通过委托来实现的。 大家想象一下这个情景,经理有一个项目,计划A君负责美工方面,B君负责程序方面,将项目一分为二;于是一天,在用餐的时候告诉他们这个计划。 发布者:经理---------@2 订阅者订阅这个事件原因:A,B君是经理的部下 -------------@3 事件:经理分配了A,B一个项目-------------@4 触发事件的原因:经理有个计划----------------@5 通知方式(委托):”在用餐的时候告诉“方式----------------@6 public delegate void OneThing(object sender, CustomEventArgs e);定义一个委托,返回值为空,委托名OneThing,相当于@1中的EventHandler,有两个参数分别为触发事件的对象和事件信息。 Custom EventArgs必须继承于EventArgs public class CustomEventArgs : EventArgs

论C#中的委托与事件

论C#中的委托与事件 在C#里,委托与事件类是两个不易理解的概念。主要阐述对委托与事件的理解,同时结合Observer设计模式与.NET Framework规范,针对生活中的案例来辨析委托与事件的应用。 标签:委托;事件Observer设计模式;.NET Framework C#中的委托类似于C++中的函数指针,功能却更多。事件是在委托的基础上的一种结构,类似于委托的变量,在界面的控件中处处都有应用。 1 什么是委托 委托的申明格式:修饰符delegate 返回值数据类型委托名(形参列表)。 例如:Delegate int AbcDel(string s, bool b);是一个委托申明,每一个委托都有自己的签名,就是说AbcDel这个委托有string 和bool类型的形参,返回一个int类型数据,即具有这样的函数签名。委托类似于函数指针,它能够引用函数,通过传递地址的机制完成。委托是一个类,当对它实例化时,要提供一个引用函数,将其作为它构造函数的参数。例如:private int AbcFun (string str, bool bln){},则可以把这个函数传给AbcDel的构造函数,因为它们签名一致。AbcDel sd = new SomeDelegate(AbcFun),sd 引用了AbcFun,也就是说,AbcFun已被sd所登记注册,如果你调用sd,AbcFun这个函数即会被调用。 2 事件的理解 事件的申明格式:修饰符event 委托名事件名; 例如:public event AbcDel Boil;//AbcDel为委托名 Boil事件的声明与之前委托变量sd的声明唯一的区别是多了event关键字。声明事件类似于声明一个委托类型的变量。 3 Observer设计模式 假设热水器系统由两部分组成:热水器、警报器,由不同厂商进行了组装。热水器仅负责烧水;警报器在水烧开时发出警报,当水温超过95度,就发出警报。我们需要应用委托与事件来模拟此过程。 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。Observer模式是一种松耦合的设计模式。它包括两类对象:

unity3D学习之委托、事件全解析(二)

废话就不多说了,直接进入今天的主题-事件在我们所接触到的事件一般分两种:一种是自定义的,自定义的事件需要自己对其进行赋值。 一种是控件提供方定义的,如:ngui,控件事件只需要查找控件定义的事件列表,选择所需要的进行操作即可。 当然,我们的话题是上面第一种啦。 实例模拟场景为:文章来自【狗刨学习网】 游戏战斗中,猪脚在指定的一片区域中,存在4只怪物,他的目的就是一只一只找到并消灭该区域的怪物。 简易流程:查询目标->行走->攻击,依次循环 ok,在此,我用代码快速模拟这样一个情景,建立一个Hero类,如下: using UnityEngine; using System.Collections; using System.Collections.Generic; using System;

// 英雄角色 public class Hero : MonoBehaviour { //当前目标id public int TargetID=0; public List ListMonster; void Start() { InvokeRepeating("selectTarget", 0.3f, 0.3f); } // 查询目标 private void selectTarget() { if (TargetID==0) { if (ListMonster.Count > 0) { for (int i = 0; i <= ListMonster.Count; i++) { TargetID = ListMonster[i];[/i] WalkToTarget(TargetID);

C#委托、事件、自定义事件的理解

C#委托、事件、自定义事件的理解 一、委托 委托类似于函数指针,但函数指针只能引用静态方法,而委托既能引用静态方法,也能引用实例方法。委托使用分三步:1、委托声明。2、委托实例化。3、委托调用。 例程一: using System; namespace 委托 { delegate int NumOpe(int a,int b); //委托声明 class Class1 { static void Main(string[] args) { Class1 c1 = new Class1(); NumOpe p1 = new NumOpe(c1.Add); //委托实例化 Console.WriteLine(p1(1,2)); //委托调用 Console.ReadLine(); } private int Add(int num1,int num2) { return(num1+num2); } } } 例中,委托NumOpe引用了方法Add。 委托声明了以后,就可以象类一样进行实例化,实例化时把要引用的方法(如:Add)做为参数,这样委托和方法就关联了起来,就可以用委托来引用方法了。 委托和所引用的方法必须保持一致: 1)参数个数、类型、顺序必须完全一致。2)返回值必须一致。 二、事件 事件有很多,比如说鼠标的事件:MouserMove,MouserDown等,键盘的事件:KeyUp,KeyDown,KeyPress。 有事件,就会有对事件进行处理的方法,而事件和处理方法之间是怎么联系起来的呢?委托就是他们中间的桥梁,事件发生时,委托会知道,然后将事件传递给处理方法,处理方法进行相应处理。

C#委托与事件

我们抛弃各种C#参考书中桀骜难懂的事件与委托概念,设想一个情景来理解事件与委托的使用:有一家IT公司,董事长不希望自己的雇员在上班时间玩游戏,但又不可能每时每刻都盯着每个雇员,因此,他希望使用一种新的方式实现监视雇员的效果:如果有雇员违反规定,某个设备或专门的监查人员将自动发出一个消息通知他,董事长只需要在事情发生时进行处理。 因此,这个用例实际上是两种类型——董事长类与雇员类——之间的交互,下面的代码将给读者展示如何使用委托与事件机制实现这种交互: 首先,我们需要在董事长类与雇员类之间定义一个委托类型,用于传递两者之间的事件,这个类型就是一个监视设备或专门负责打小报告的监查人员: public delegate void DelegateClassHandle(); 定义一个委托的过程类似方法的定义,但它没有方法体。定义委托一定要添加关键字delegate。由于定义委托实际上相当一个类,因此可以在定义类的任何地方定义委托。另外,根据委托的可见性,也可以添加一般的访问修饰符,如public、private和protected。 委托的返回值类型为void,这并非表示委托类型本身带有返回值,该返回值类型是指委托的目标函数类型,即它委托的一个事件处理函数返回值是void类型。 新建一个雇员类Employee,其代码如下: public class Employee { public event DelegateClassHandle PlayGame; public void Games() { if (PlayGame != null) { PlayGame(); } } } 雇员类Employee代码中定义了一个DelegateClassHandle类型的事件PlayGame,它的定义方式也很特殊,首先必须使用关键字event,表示PlayGame是一个事件,同时还必须声明该事件的委托类型为DelegateClassHandle,即将来由该类型的委托对象负责通知事件。 如果有雇员开始玩游戏,它将执行Games方法,而只要该方法一被调用,就会触发一个事件PlayGame,然后董事长就会收到这个事件的消息——有人在玩游戏了。 董事长类代码如下,他有一个方法Notify用于接收消息: public class Admin { public void Notify() {

c#中如何深入理解“事件与委托”

C#中如何深入理解“事件与委托”?(初学者必看) 2008年01月19日星期六 22:57 事件与委托似乎很难以理解,这是因为它们的使用方式与常用的编码有很大的差别,例如通常编写的都是同步代码,调用一个类型的方法,会即刻出现方法执行的结果,这是符合逻辑的。但在某些情况中,同步代码未必满足需求,拿公共汽车来打个比方,如果交通管制中心希望每一辆公车到达一个站点时都发送给自己一个信号以便自己能够随时掌握交通状况,使用同步代码,公汽对象肯定需要调用管制中心对象,这样就出现了我们一直不愿意看到的情况:两个类型紧密地耦合在一起。既然要其它类型对自己的行为作出反应,亲自调用其类型的方法似乎不可避免,在同步代码中,很难避免这种紧密的类型调用关系。 另一个差别是在一般情况下,我们只将属性作为参数传递给方法,而很少会考虑将一个方法传递给另一个方法。 我们抛弃各种C#参考书中桀骜难懂的事件与委托概念,设想一个情景来理解事件与委托的使用:有一家IT公司,董事长不希望自己的雇员在上班时间玩游戏,但又不可能每时每刻都盯着每个雇员,因此,他希望使用一种新的方式实现监视雇员的效果:如果有雇员违反规定,某个设备或专门的监查人员将自动发出一个消息通知他,董事长只需要在事情发生时进行处理。 因此,这个用例实际上是两种类型——董事长类与雇员类——之间的交互,下面的代码将给读者展示如何使用委托与事件机制实现这种交互: 首先,我们需要在董事长类与雇员类之间定义一个委托类型,用于传递两者之间的事件,这个类型就是一个监视设备或专门负责打小报告的监查人员: public delegate void DelegateClassHandle(); 定义一个委托的过程类似方法的定义,但它没有方法体。定义委托一定要添加关键字delegate。由于定义委托实际上相当一个类,因此可以在定义类的任何地方定义委托。另外,根据委托的可见性,也可以添加一般的访问修饰符,如public、private和protected。 委托的返回值类型为void,这并非表示委托类型本身带有返回值,该返回值类型是指委托的目标函数类型,即它委托的一个事件处理函数返回值是void类型。 新建一个雇员类Employee,其代码如下: public class Employee { public event DelegateClassHandle PlayGame; public void Games() { if (PlayGame != null) { PlayGame(); } } }

委托和事件的区别

委托和事件的区别(讲的很详细)--转 委托和事件在 .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:

委托与事件的区别

委托与事件的区别 委托和事件在 .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 }

C中的委托的使用和讲解

C#中的委托引言 委托和事件在.NetFramework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.NetFramework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。 将方法作为方法的参数 我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语: 1publicvoid GreetPeople(string name){ 2//做某些额外的事情,比如初始化之类,此处略 3EnglishGreeting(name); 4} 1publicvoid EnglishGreeting(string name){ 2Console.WriteLine("Morning,"+name); 3} 暂且不管这两个方法有没有什么实际意义。GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“JiYF”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出“Morning,JiYF”。 现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法: 1publicvoid ChineseGreeting(string name){ 2Console.WriteLine("早上好,"+name); 3} 这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting 问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据: 1publicenum Language{ 2English,Chinese 3} 1publicvoid GreetPeople(string name,Languagelang){ 2//做某些额外的事情,比如初始化之类,此处略 3swith(lang){

委托和事件的直接理解

初学者在理解委托和事件时常常被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.output);//实例的初始化 dc.d(2,3); } } } 解释一下"关键": 实际上 public delegate void fHandler(int a);可以看成如下: class fHandler {.....} 类内部由编译器自动完成,是一个sealed类通过反汇编可以看到,是一个类的声明,它检查加入自己的函数的信息,如,返回值和参数类型

C委托的妙文让你知道如何发挥委托的作用

C委托的妙文让你知道如何发挥委托的作用 Revised final draft November 26, 2020

委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别 (biè)得慌,混身不自在。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。 将方法作为方法的参数 我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语: 以下为引用的内容: public void GreetPeople(string name) { // 做某些额外的事情,比如初始化之类,此处略 EnglishGreeting(name); } public void EnglishGreeting(string name) { Conso le.WriteLine(”Morning, ” name); } 暂且不管这两个方法有没有什么实际意义。GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“Jimmy”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出“Morning, Jimmy”。 现在假设这个程序需要进行全球化,哎呀,不好了,我是人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法: 以下为引用的内容: public void ChineseGreeting(string name){ Console.WriteLine(”早上好, ” name); } 这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting 问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:以下为引用的内容: view plaincopy to clipboardprint? 1. public enum Language{ 2. English, Chinese 3. }

菜鸟入门 认识C#中的委托和事件

引言 委托和事件在.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:

C#中的委托(Delegate)和事件(Event)-例子解释

https://www.360docs.net/doc/ce10003423.html,/uid-576762-id-2733751.html C#中的委托(Delegate)和事件(Event)2007-11-30 11:40:00 分类: 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式——观察者(Observer)有一个参考。 委托和事件应该是C#相较于C++等之前的非托管的语言提出的一个新的术语(term)。“旧瓶装新酒”这样的描述似乎有些“贬义”,但确实是这样。委托也好,事件也好最初的起源是C/C++中的函数指针,关于函数指针的简单介绍可以参见我以前的一篇《C/C++中指向函数的指针》。不过旧瓶装新酒没有什么不好,反而给人添加了许多新滋味。 1. Function pointer--the origin of delegates and events . 书回正传,既然函数指针是它们(委托和事件)的起源。那我们先看看什么情况下我们需要函数指针。函数指针最常用的方式就是回调(callback)——在函数休内回调主函数里的函数。有些绕口,看代码: //Platform: WinXP + VC6.0 #include #include using namespace std; void max(int a,int b) { cout<<"now call max("<b?a:b; cout<

深入理解C#中的委托和事件委托的定义

【IT168 专稿】委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、委托和事件对Observer设计模式的意义、.Net Framework中的委托和事件,对它们的中间代码也做了讨论。 将方法作为方法的参数 我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语: 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);

c#委托与事件详解

c#委托与事件详解.txt花前月下,不如花钱“日”下。叶子的离开,是因为风的追求还是树的不挽留?干掉熊猫,我就是国宝!别和我谈理想,戒了!委托和事件在 .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:

委托和事件(精选易懂实例代码)

using System; /*要仔细研究,因为这是创新*/ /* 步骤1,声明delegate对象*/ public delegate void MyEventHandler(object sender, EventArgs e); class EventTest { /* 2.实现方法,这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型*/ public static void MyEventFunc(object sender, EventArgs e) { Console.WriteLine("My event is ok!"); } /*3.通过委托定义事件*/ private event MyEventHandler myevent; /*4.订阅方法*/ public EventTest() { this.myevent += new MyEventHandler(MyEventFunc); } //5.触发事件 public void RaiseEvent() { EventArgs e = new EventArgs(); if (myevent != null) { myevent(this, e); } } public static void Main() { EventTest et = new EventTest(); Console.Write("Please input a:"); string s = Console.ReadLine(); if (s == "a") { et.RaiseEvent(); } else { Console.WriteLine("Error"); } Console.ReadKey(); } } /*〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓*/ /* 步骤1,声明delegate对象*/ public delegate void MyEventHandler(object sender, EventArgs e); class EventTest { /* 2.实现方法,这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型*/ public static void MyEventFunc(object sender, EventArgs e)

相关文档
最新文档