代理(Delegate)的例子

delegate void MyDelegate(string str,int index);    // 声明代理

class Test
{
public static void Show(string str, int index) // 声明方法
{
Console.WriteLine("Show"+str+index.ToString());
} public static void Main(string[] args)
{
MyDelegate md = new MyDelegate(Show); // 1.实例化代理,传入方法
md("hello world", ); // 2.传入参数
}
}

事件结合代理的完整例子

// 事件用到的代理,以般以×××Handler的格式进行命名
private delegate void CryHandler(); // 无参代理 // 玩具小鸭的类
class Duck
{
// 定义小鸭的唱歌事件
public event CryHandler DuckCryEvent; public Duck()
{
// 把小鸭唱歌的事件挂接到Cry方法上
DuckCryEvent += new CryHandler(Cry); // 注册事件,传入方法
} // 小鸭唱歌事件对应的处理方法
public void Cry()
{
Console.WriteLine("我是一只小鸭,呀呀呀....");
} // 小鸭被摇动
public void BeShaked() //执行方法,引发cry事件
{
DuckCryEvent(); // 执行事件,传入参数
}
} class MyClass
{
public static void Main3(string[] args)
{
// 买一只小鸭
Duck d = new Duck();
// 摇一摇小鸭,它就会调触发小鸭的Cry事件,小鸭就会唱歌
d.BeShaked();
}
}

参考:

事件与委托的区别?

实际上,事件是对委托的封装。如果不进行封装,让委托暴露给调用者,调用者就可以把委托变量重新引用到新的委托对象,也就删除了当前要调用的方法列表;更糟糕的是,公共的委托成员打破了封装不仅导致代码难以维护和调试,而且会导致应用程序有安全风险。

参考:

怎么理解事件对函数列表的保护作用呢?看下面的例子。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Test
{
public delegate void MyDelegate(string str, int index); // 代理可以声明在类的外部
public event MyDelegate MyHandler; // 事件必须在类内部定义 public void FireEvent()
{
MyHandler = Show; // 事件的函数列表交由定义方维护,不会被调用者修改!
MyHandler += Show;
MyHandler("test", ); // 会调用两次Show()
} public void Show(string str, int index)
{
Console.WriteLine("Show : " + str + index.ToString());
}
} class Program
{
static void Main(string[] args)
{
// 使用代理
Test t = new Test();
Test.MyDelegate my = new Test.MyDelegate(t.Show); // 修改参数,调用方甚至可以修改代理的函数列表
my += DoSomething; // 调用方可自由修改被调用方定义的委托的函数列表!
//my.Invoke("这是Program.DoSomething()", 2); // 运行结果:先调用t.Show()再调用DoSomething() // 使用事件
t.MyHandler += DoSomething;
// t.MyHandler("12", 1); // 报错:Test.MyHandler只能出现在 += 或 -= 的左边(从类型“Test”中使用时除外)
// t.MyHandler.Invoke("这是Program.DoSomething()", 2); // 错误,事件不存在Invoke()调用,只会被调用方触发,再由事件定义方自行来调用
t.FireEvent(); // 运行结果:会发现DoSomething()没有被调用,因为事件中的函数列表由被调用方维护,不会被调用方修改!
Console.ReadLine();
} public static void DoSomething(string str, int index)
{
Console.WriteLine("DoSomething");
}
} }

可见,如果使用delegate代理,代理的函数列表会暴露给调用者,调用者可以任意修改它(只要符合代理声明的方法传参、返回值即可)!这样被调用者将无法约束调用者的行为。

而如果使用evnet事件,由于调用者只能触发事件,事件只能由被调用方来调用,所以即便调用者尝试修改事件的函数列表,但真到调用时也无法改变事件的函数列表。即函数列表始终由被调用者来维护,调用者的行为被约束了!

【C#】事件(Event)和代理/委托(Delegate)的更多相关文章

  1. C# 代理/委托 Delegate

    本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...

  2. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  3. C#总结(二)事件Event 介绍总结

    最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...

  4. 事件Event 介绍总结

    最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...

  5. 重温委托(delegate)和事件(event)

    1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...

  6. 关于C# 委托(delegate)与事件(event)的用法及事例

    C#中的委托和事件对于新手可能会有一点难理解,所以先从一个小例子入手,以便能更好的理解其如何使用.有一个学生每天定闹钟在早上6点起床,所以当每天早上6点的时候,闹钟就会响起来,从而学生才会按时起床. ...

  7. C#中的委托(Delegate)和事件(Event)

    原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...

  8. (转)C#中的委托(Delegate)和事件(Event)

    转自:http://blog.chinaunix.net/uid-576762-id-2733751.html   把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写 ...

  9. 事件[event]_C#

    事件(event): 1.       事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...

随机推荐

  1. springmvc ModelAndView 和 Model

    @RequestMapping("") public ModelAndView index(HttpSession session) { Object data = session ...

  2. Intellij IDEA 设置代码着色

    从visual studio到Eclipse再到Intllij IDEA,其实每个编译器都有自己的风格,但是就美观上来说,个人觉得还是visual studio的代码着色比较美观,exlipse次之, ...

  3. HDUOJ---2082

    找单词 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  4. XP和Win 7双系统安装说明和注意事项

    安装前说明: 1.先装XP,再装Windows 7,最好不要反过来,不然XP不会把Windows 7的启动管理器给覆盖掉,会麻烦些.总之遵循“旧版本到新版本”安装原则. 2.如果分区不够大,请用以下软 ...

  5. $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别

    当 DOM(文档对象模型) 已经加载,并且页面(包括图像)已经完全呈现时,会发生 ready 事件.ready() 函数仅能用于当前文档,因此无需选择器.所以document选择器可以不要,那么就可以 ...

  6. go 学习 ---package

    1.包简述 GO本身没有项目的概念,只有包,包括可执行包和不可执行包,而不管什么包,都应该包含在 $GOPATH/src 目录下,GO命令和编译器会在 $GOPATH/src 目录下搜索相应的包.比如 ...

  7. 摘:VC开发数据库基础之ADO篇

    一.ADO简介ADO(ActiveX Data Object)是Microsoft数据库应用程序开发的新接口,是建立在OLE DB之上的高层数据库访问技术,请不必为此担心,即使你对OLE DB,COM ...

  8. AP_付款方式汇总:标准付款、退款退货付款、撤销付款(概念)

    2014-06-04 Created By BaoXinjian

  9. Leet Code -- Unique BST

    对于数字n(大于1).从1到n有多少种binary search tree(BST序列)?当n=3时,BST序列为: 1         3     3    2     1     \       ...

  10. ucosii事件控制块------消息邮箱与消息队列

    UCOSII 使用叫做事件控制块(ECB)的数据结构来描述诸如信号量.邮箱(消息邮箱)和消息队列这些事件 #define OS_EVENT_EN (((OS_Q_EN > 0u) &&a ...