C#事件与委托的区别
C#事件与委托的区别
1. 委托
事件是利用委托来定义的,因此先解释委托。委托是一个类,它与其他类如int,string等没有本质区别,int代表的是所有的整形,而string代表的是字符串,委托则代表的是一类方法,这类方法具有相同返回类型和相同参数。委托的定义:
public delegate void CalculatorHandler(int x,int y);
从CalculatorHandler这个委托的定义可以看出,它反应的是一类方法,这类方法的返回类型是void,两个参数是(int x,int y),因此以后所有具有这样特征的方法都可以用这个委托来代替,现有以下这个方法:
static void Add(int x, int y)
{
Console.WriteLine("x+y={0}",x+y);
}
首先要将这个方法赋值给这个委托才可以使用,就如普通的类赋值一样,
CalculatorHandler calhandler = new CalculatorHandler(Add)
当然你也可以像给一个整形赋值一样,这样赋值:
CalculatorHandler calhander = Add;
当要调用这个方法的时候,你可以就像使用方法一样使用委托,
calhander(3,4);
委托也可以绑定多个方法,当调用这个委托时,会调用所有已经绑定了的方法,如现在还有这样的方法:
static void Multiply(int x, int y)
{
Console.WriteLine("x*y={0}",x*y);
}
只需在calhandler基础上多绑定个方法,具体语法:
calhander += Multiply;
这样当调用
calhander(3,4);
会同时调用Add和Multiply这两个方法,你也可以利用“-=”解绑方法:
calhander -= Multiply;
这样再次调用这个委托,则只会调用Add这个方法。
2. 事件
一说到事件总会有发布者(publisher)和订阅者(subscriber),发布者定义了一个事件,订阅者订阅了该事件(指的是当该事件触发时,订阅者做出什么样的反应,即利用相应的函数去处理)。该函数的定义与定义该事件的委托配套。代码如下:

public delegate void MessageEventHandler();
class Publisher
{
public event MessageEventHandler MessageEvent;
public void DoSomething()
{
Console.WriteLine("等待消息");
Console.WriteLine("首长来啦!!!");
OnMessageEvent();
}
public void OnMessageEvent()
{
if (MessageEvent != null)
{
MessageEvent();
}
}
}
class Subscriber
{
public Subscriber(Publisher p)
{
p.MessageEvent += Response;
} public void Response()
{
Console.WriteLine("首场,辛苦了");
}
} class Program
{
static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber(p);
p.DoSomething();
Console.ReadKey();
}
}
}

这就是事件的基本用法,但是事件与委托到底有什么区别呢,从上面的代码可以看出,事件是根据委托来定义的,
public event MessageEventHandler MessageEvent
其实它是利用委托来规定订阅者处理函数的类型(相同的返回类型和参数即为一类),然后可以方便在发布者自身的类中来触发订阅者的一些方法。
但是为什么要事件呢,要实现这些,我仅用委托也可以实现呀,如下代码:

public delegate void MessageEventHandler();
class Publisher
{
public MessageEventHandler MessageEvent;//为了方便,委托名与原来的事件名相同。
// public event MessageEventHandler MessageEvent;
public void DoSomething()
{
Console.WriteLine("等待消息");
Console.WriteLine("首长来啦!!!");
OnMessageEvent();
}
public void OnMessageEvent()
{
if (MessageEvent != null)
{
MessageEvent();
}
}
}
class Subscriber
{
public Subscriber(Publisher p)
{
p.MessageEvent += Response;
} public void Response()
{
Console.WriteLine("首场,辛苦了");
}
}
class Program
{
static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber(p);
p.DoSomething();
Console.ReadKey();
}
}

这样子也同样可以产生相同的结果。
但是当客户端如下调用呢?
Publisher p = new Publisher();
Subscriber s = new Subscriber(p);
p.DoSomething();
p.MessageEvent();
Console.ReadKey();
客户端是不是能随意让发布者产生事件,因此我们可否将发布者的委托定义为private,因为只有发布者的内部才能触发事件嘛,其他人怎么可以?但是这样订阅者就无法订阅了,那我们是否可以增加绑定可解除的函数来订阅此委托呢?

public delegate void MessageEventHandler();
class Publisher
{
private MessageEventHandler MessageEvent;
// public event MessageEventHandler MessageEvent;
public void DoSomething()
{
Console.WriteLine("等待消息");
Console.WriteLine("首长来啦!!!");
OnMessageEvent();
}
public void OnMessageEvent()
{
if (MessageEvent != null)
{
MessageEvent();
}
}
public void Add_MessageEvent(MessageEventHandler m)
{
MessageEvent += m;
}
public void Reomove_MessageEvent(MessageEventHandler m)
{
MessageEvent -= m;
}
}
class Subscriber
{
public Subscriber(Publisher p)
{
//p.MessageEvent += Response;
p.Add_MessageEvent(Response);
} public void Response()
{
Console.WriteLine("首场,辛苦了");
}
}
class Program
{
static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber(p);
p.DoSomething();
Console.ReadKey();
}
}
}

这样就可以实现与事件一样的功能,因此为了方便微软为我们提供了事件访问器,何为事件访问器?

public delegate void MessageEventHandler();
class Publisher
{
private MessageEventHandler MessageEvent;
// public event MessageEventHandler MessageEvent; public event MessageEventHandler TestEvent
{
add
{
lock (MessageEvent)
{
MessageEvent += value;
}
}
remove
{
lock (MessageEvent)
{
MessageEvent -= value;
} }
}
public void DoSomething()
{
Console.WriteLine("等待消息");
Console.WriteLine("首长来啦!!!");
OnMessageEvent();
}
public void OnMessageEvent()
{
if (MessageEvent != null)
{
MessageEvent();
}
} }
class Subscriber
{
public Subscriber(Publisher p)
{
p.TestEvent += Response; } public void Response()
{
Console.WriteLine("首场,辛苦了");
}
}
class Program
{
static void Main(string[] args)
{
Publisher p = new Publisher();
Subscriber s = new Subscriber(p);
p.DoSomething();
Console.ReadKey();
}
}

以上的代码就是利用事件访问器来让委托绑定订阅者的方法,事件访问器中的add和remove能自动编译为+=和-=。
通过reflector,我们可以看到一个事件是如何定义的:

它是申明一个私有的委托:
private MessageEventHandler MessageEvent;
另外利用两个函数来绑定与解除订阅者的方法。
C#事件与委托的区别的更多相关文章
- C# 事件和委托
相信大家在面试的时候会经常问到事件和委托的区别,为什么.net中需要事件和委托这样类似的问题吧,对于一些初学者来说可平时用的过程中也不知道为什么, 只知道这样用,而对于其中的实现机制不是很清楚, 所以 ...
- 事件、委托、委托方法的总结(使用EventHandler<>)
在C#中,定义事件.委托.委托方法可以使用类库内的EventHandler泛型委托来定义事件.并根据该泛型委托定义实现方法: 同样您也可以自定义委托 来定义事件以及 根据自定义的委托来定义实现事件的方 ...
- C#基础精华07(委托事件,委托的使用,匿名方法)
1.委托概述 委托是一种数据类型,像类一样(可以声明委托类型变量).方法参数可以是int.string.类类型 void M1(int n){ } √ void M2(string s){ } √ ...
- [C#参考]事件和委托的关系
前面说了委托,接下来就要说一说事件了,同时最后再说一下委托和事件的区别. 事件和委托很相似,事件就好像是被简化的针对特殊用途的委托.看下面的图: 从这张图中能看到,事件是发布者的一个成员,它不是类型. ...
- C#事件与委托详解【精华 多看看】
Delegate delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类.与其它的类不同,delegate类能够拥有一个签名(signature),并且它"只能持有与 ...
- C#基础知识之事件和委托
本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.委托的调用方式.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码 ...
- 解密jQuery事件核心 - 委托设计(二)
第一篇 http://www.cnblogs.com/aaronjs/p/3444874.html 从上章就能得出几个信息: 事件信息都存储在数据缓存中 对于没有特殊事件特有监听方法和普通事件都用ad ...
- c#事件与委托
C#.net 目录(?)[-] 将方法作为方法的参数 将方法绑定到委托 事件的由来 事件和委托的编译代码 委托事件与Observer设计模式 范例说明 Observer设计模式简介 实现范例的Obse ...
- 《C#高级编程》学习笔记------C#中的事件和委托
本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件 引言 委托 和 事件在 .Net Framework中的应用 ...
随机推荐
- easyUI 插件写法 ---Validatebox 插件为例
easyui 的每个组件都有属性.方法和事件.用户可以很容易地对这些组件进行扩展. js地址:jquery-easyui-1.3.3/jeasyui-extensions/jeasyui.extens ...
- poj 1061青蛙的约会
青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 90083 Accepted: 16257 Descripti ...
- HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)
Problem Description In this problem, you are given a string s and q queries. For each query, you sho ...
- Android手游《》斗地主完整的源代码(支持单机和网络对战)
Android手游<斗地主>完整的源代码(支持单机和网络对战)下载.一个很不错的源代码. 斗地主掌游是一个独特的国内社会斗地主棋牌游戏,之后玩家可以下载网上斗地主和全世界.掌游斗地主特点: ...
- Leetcode:convert_sorted_array_to_binary_search_tree
一. 称号 排序后的数组成二叉搜索树. 二. 分析 BST的中序遍历是一个sorted-array,再构造回去成一个BST,先将中间的元素作为根节点,这个节点的左右各自是左子树和右子树 ...
- JAVA设计模式(09):结构化-代理模式(Proxy)
一,定义: 代理模式(Proxy):为其它对象提供一种代理以控制对这个对象的訪问. 二.其类图: 三,分类一:静态代理 1,介绍:也就是须要我们为目标对象编写一个代理对象,在编译期就生成了这个代理对 ...
- HDU 3415 Max Sum of Max-K-sub-sequence 最长K子段和
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415 意甲冠军:环.要找出当中9长度小于等于K的和最大的子段. 思路:不能採用最暴力的枚举.题目的数据量是 ...
- 【转】Uiautomator Api浅析
原文地址:http://blog.sina.com.cn/s/blog_ae2575ff01018b2o.html uiautomator api: http://android.toolib.net ...
- java界面编程(8) ------ 组合框(下拉列表)
本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 与一组单选button的功能类似,组合框(下拉列表)也是强制用户从一组可能的元素 ...
- GCD && Run Loops学习笔记
1.GCD 使用不同优先级的若干个队列乍听起来非常直接,只是,我们强烈建议,在绝大多数情况下使用默认的优先级队列就能够了.假设运行的任务须要訪问一些共享的资源,那么在不同优先级的队列中调度这些任务非常 ...