C#中委托和事件的区别

比特逐影鹤
• 阅读 2716

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

□ 通过委托执行方法

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的源代码。

1

可见,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元素,译者注)发生事件时,无论这个事件发生在这个元素上还是从内层元素经冒泡而
待兔 待兔
4年前
《C# 教程》菜鸟教程学习笔记
C简介下面列出C一些重要的功能:布尔条件(BooleanConditions)自动垃圾回收(AutomaticGarbageCollection)标准库(StandardLibrary)组件版本(AssemblyVersioning)属性(Properties)和事件(Events)委托(D
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年前
C# 事件与委托
一些小概念,防止自己太久不用忘记了事件委托:Action<int,int,string….(maxnumberof16parameters)a永远没有返回值,最多16个泛型输入参数e.g.:StaticvoidPrintStr(stringstr){   Console.WriteLine(str);
Wesley13 Wesley13
3年前
C#中委托和事件的区别
大致来说,委托是一个类,该类内部维护着一个字段,指向一个方法。事件可以被看作一个委托类型的变量,通过事件注册、取消多个委托或方法。本篇分别通过委托和事件执行多个方法,从中体会两者的区别。□通过委托执行方法classProgram{staticvoidMain(stringargs){
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方法结束异步