C#中委托和事件的区别

Wesley13
• 阅读 554

大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法。事件可以被看作一个委托类型的变量,通过事件注册、取消多个委托或方法。本篇分别通过委托和事件执行多个方法,从中体会两者的区别。

□ 通过委托执行方法

class Program

{

static void Main(string[] args)

{

Example example = new Example();

example.Go();

Console.ReadKey();

}

}

public class Example

{

public delegate void DoSth(string str);

internal void Go()

{

//声明一个委托变量,并把已知方法作为其构造函数的参数

DoSth d = new DoSth(Print);

string str = "Hello,World";

//通过委托的静态方法Invoke触发委托

d.Invoke(str);

}

void Print(string str)

{

Console.WriteLine(str);

}

}

以上,

○ 在CLR运行时,委托DoSth实际上就一个类,该类有一个参数类型为方法的构造函数,并且提供了一个Invoke实例方法,用来触发委托的执行。
○ 委托DoSth定义了方法的参数和返回类型
○ 通过委托DoSth的构造函数,可以把符合定义的方法赋值给委托
○ 调用委托的实例方法Invoke执行了方法

但,实际上让委托执行方法还有另外一种方式,那就是:委托变量(参数列表)

public class Example

{

public delegate void DoSth(object sender, EventArgs e);

internal void Go()

{

//声明一个委托变量,并把已知方法作为其构造函数的参数

DoSth d = new DoSth(Print);

object sender = 10;

EventArgs e = new EventArgs();

d(sender, e);

}

void Print(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

}

以上,

○ 委托DoSth的参数列表和方法Print的参数列表还是保持一致
○ 委托DoSth中的参数object sender通常用来表示动作的发起者,EventArgs e用来表示动作所带的参数。

而实际上,委托变量(参数列表),事件就是采用这种形式执行方法的。

□ 通过事件执行方法

public class Example

{

public delegate void DoSth(object sender, EventArgs e);

public event DoSth myDoSth;

internal void Go()

{

//声明一个委托变量,并把已知方法作为其构造函数的参数

DoSth d = new DoSth(Print);

object sender = 10;

EventArgs e = new EventArgs();

myDoSth += new DoSth(d);

myDoSth(sender, e);

}

void Print(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

}

以上,

○ 声明了事件myDoSth,事件的类型是DoSth这个委托
○ 通过+=为事件注册委托
○ 通过DoSth委托的构造函数为事件注册委托实例
○ 采用委托变量(参数列表)这种形式,让事件执行方法

而且,通过+=还可以为事件注册多个委托。

public class Example

{

public delegate void DoSth(object sender, EventArgs e);

public event DoSth myDoSth;

internal void Go()

{

//声明一个委托变量,并把已知方法作为其构造函数的参数

DoSth d = new DoSth(Print);

DoSth d1 = new DoSth(Say);

object sender = 10;

EventArgs e = new EventArgs();

//为事件注册多个委托

myDoSth += new DoSth(d);

myDoSth += new DoSth(d1);

myDoSth(sender, e);

}

void Print(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

void Say(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

}

以上,通过+=为事件注册1个或多个委托实例,实际上,还可以为事件直接注册方法。

public class Example

{

public delegate void DoSth(object sender, EventArgs e);

public event DoSth myDoSth;

internal void Go()

{

object sender = 10;

EventArgs e = new EventArgs();

//为事件注册多个委托

myDoSth += Print;

myDoSth += Say;

myDoSth(sender, e);

}

void Print(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

void Say(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

}

□ 通过EventHandler执行方法

先来看EventHandler的源代码。

C#中委托和事件的区别

可见,EventHandler就是委托。现在就使用EventHandler来执行多个方法。

public class Example

{

public event EventHandler myEvent;

internal void Go()

{

object sender = 10;

EventArgs e = new EventArgs();

//为事件注册多个委托

myEvent += Print;

myEvent += Say;

myEvent(sender, e);

}

void Print(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

void Say(object sender, EventArgs e)

{

Console.WriteLine(sender);

}

}

总结:
○ 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
○ 触发委托有2种方式: 委托实例.Invoke(参数列表),委托实例(参数列表)
○ 事件可以看作是一个委托类型的变量
○ 通过+=为事件注册多个委托实例或多个方法
○ 通过-=为事件注销多个委托实例或多个方法
○ EventHandler就是一个委托

点赞
收藏
评论区
推荐文章
Dax Dax
3年前
jQuery 的事件绑定和事件委托(事件代理)
简单以jQuery的on()方法为例说明:API:1.on(events,selector,data,handler) 如果on()方法的selector参数为空,事件处理程序就被称为直接绑定。每当在被绑定元素上(如下例中被绑定的document元素,译者注)发生事件时,无论这个事件发生在这个元素上还是从内层元素经冒泡而
Wesley13 Wesley13
3年前
C#委托和事件
0\.前言事件和委托是C中的高级特性,也是C中很有意思的一部分。出现事件的地方,必然有委托出现;而委托则不一定会有事件出现。那为什么会出现这样的关系呢?这就需要从事件和委托的定义出发,了解其中的内在。1\.委托说起委托,就不得不回忆一下之前在Linq篇中介绍的匿名方法,其中提到了Func和Action这两个类型
Stella981 Stella981
3年前
C# lambda 和 Linq
本章节给大家带来的是Lambda和Linq的关系Lambda:是实例化委托的一个参数,也就是一个方法Linq:是基于委托(lambda)的封装,代码重用,逻辑解耦,是一个帮助类库,linq是用泛型,委托,lamda实现的,总的来说:把对数据操作的通用部分完成,把可变的交给委托,使用者只关心可变部分。一、Lambda文章的开始
Stella981 Stella981
3年前
Logback
1\.作用Logback将写日志事件的任务委托给appender组件完成,SiftingAppender顾名思义就是筛选日志事件,具体点就是:对于Logback委托给它的日志事件,SiftingAppender会对日志事件做一些区分,然后不同的事件SiftingAppender会委托不同的appender去完成真正的写操作。假
Wesley13 Wesley13
3年前
C# 创建线程的多种方式之异步调用基础知识
创建线程一种简单的方式是委托的异步调用,Delegate类提供了BeginInvoke方法,该方法可以传递委托类型定义的参数(所以BeginInvoke参数数量是可变的),另外还有2个固定的参数回调函数委托AsynsCallBack和类型Object(如果不使用可直接赋值为null)。BeginInvoke()的返回值为IAsynResult,通过它
Wesley13 Wesley13
3年前
Java 动态代理机制分析及扩展,第 1 部分
引言Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。通过阅读本文,读者将会对Java动态代理机制有更加深入的理解
Wesley13 Wesley13
3年前
C# 事件与委托
一些小概念,防止自己太久不用忘记了事件委托:Action<int,int,string….(maxnumberof16parameters)a永远没有返回值,最多16个泛型输入参数e.g.:StaticvoidPrintStr(stringstr){   Console.WriteLine(str);
Wesley13 Wesley13
3年前
Unity事件系统
\1.前言Unity中事件/委托有着广泛的应用,本文通过封装一个简易的事件的系统,来统一管理消息的传递。此功能在简易应用或者事件较少的体现不出太好的作用,但是对于事件应用较多时,可以减少脚本之间的耦合。通过此事件系统架起不同脚本之间的桥梁,对于大量应用事件场景中具有良好的效果。\2.事件系统\2.1事件管理类管理事件的
Wesley13 Wesley13
3年前
IOS 委托和协议区别和联系 (=)
上一片大致说了一下IOS上面委托和协议的区别和联系,并且举了一个简单的例子,但是例子比较简单,今天做一个用委托模拟button回调的例子。在一个自定义View上面放一个登陆按钮,并且这个LoginView里面有一个实现ILogin的委托对象,在登陆按钮的点击事件中调用需要实现的协议函数。在一个ViewController中实现ILgin协议,并实现log
Wesley13 Wesley13
3年前
5.4 异步TCP编程(三)
5.4.3使用异步方式调用同步方法  .NETFramework提供了一种可以利用委托异步调用任何方法的技术,唯一的要求就是需要声明一个与要调用的方法具有相同签名的委托。对于任何一个方法,如果希望异步执行,最简单的方法就是通过调用委托的BeginInvoke方法开始异步执行,然后执行其他操作,最后调用委托的EndInvoke方法结束异步