【C#】事件(Event)和代理/委托(Delegate)
代理(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();
}
}
参考:
事件与委托的区别?
实际上,事件是对委托的封装。如果不进行封装,让委托暴露给调用者,调用者就可以把委托变量重新引用到新的委托对象,也就删除了当前要调用的方法列表;更糟糕的是,公共的委托成员打破了封装不仅导致代码难以维护和调试,而且会导致应用程序有安全风险。
参考:
- https://stackoverflow.com/questions/29155/what-are-the-differences-between-delegates-and-events
- http://blog.csdn.net/hit_why/article/details/54604908
- https://www.cnblogs.com/wujingtao/p/5196834.html
怎么理解事件对函数列表的保护作用呢?看下面的例子。
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)的更多相关文章
- C# 代理/委托 Delegate
本文转载自努力,努力,努力 1. 委托的定义:委托是函数的封装,它代表一"类"函数.他们都符合一定的签名:拥有相同的参数列表,返回值类型.同时,委托也可以看成是对函数的抽象,是函数 ...
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- C#总结(二)事件Event 介绍总结
最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...
- 事件Event 介绍总结
最近在总结一些基础的东西,主要是学起来很难懂,但是在日常又有可能会经常用到的东西.前面介绍了 C# 的 AutoResetEvent的使用介绍, 这次介绍事件(event). 事件(event),对于 ...
- 重温委托(delegate)和事件(event)
1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...
- 关于C# 委托(delegate)与事件(event)的用法及事例
C#中的委托和事件对于新手可能会有一点难理解,所以先从一个小例子入手,以便能更好的理解其如何使用.有一个学生每天定闹钟在早上6点起床,所以当每天早上6点的时候,闹钟就会响起来,从而学生才会按时起床. ...
- C#中的委托(Delegate)和事件(Event)
原文地址:C#中的委托(Delegate)和事件(Event) 作者:jiyuan51 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写的设计模式--观察者(Obs ...
- (转)C#中的委托(Delegate)和事件(Event)
转自:http://blog.chinaunix.net/uid-576762-id-2733751.html 把C#中的委托(Delegate)和事件(Event)放到现在讲是有目的的:给下次写 ...
- 事件[event]_C#
事件(event): 1. 事件是类在发生其关注的事情时用来提供通知的方式.例如,封装用户界面控件的类可以定义一个在单击该控件时发生的事件.控件类不关心单击按钮时发生了什么,但它需要告知派 ...
随机推荐
- Cocos2dx 学习记录 [2] 关于混合和高亮一些知识点的体会
网上有一篇博客讲的是高亮的http://www.cnblogs.com/mrblue/p/3455775.html 就是这篇,尽管代码简单,但对于刚開始学习的人的我,看的还是有些吃力的,毕竟有些内容不 ...
- supervisor介绍与安装
前言 今天同事让我帮忙安装一个叫supervisor的软件,但自己确实没接触过这个软件 自己做一下学习的记录 我首先是查询了一下supervisor的官网,初步认识一下这个软件 Supervisor是 ...
- 【LeetCode】136. Single Number (4 solutions)
Single Number Given an array of integers, every element appears twice except for one. Find that sing ...
- eclipse修改文件编码
http://topic.csdn.net/u/20080724/14/428de399-790d-442a-8340-3a5fb6dcfcee.html[修改文件编码,假设JS] 在Eclips ...
- Quartz2之入门示例
环境:XP+Myeclipse6.5+JDK1.6 quartz官网:http://www.quartz-scheduler.org/ 参考资料 1 Quartz任务调度快速入门 http://www ...
- Android清空Fragment回退栈
啊= =:国内的资料为什么都是抄来抄去的. 最后上了Stack Overflow才找到了正解. FragmentManager fragmentManager = getFragmentManager ...
- python学习笔记013——包package
1 包(模块包)package 1.1 包的定义 包是将模块以文件夹的组织形式进行分组管理的方法 1.2 作用 分类管理,有利于防止命名冲突 可以在需要时加载一个或部分模块,而不是全部模块 mypac ...
- spring boot几个初始配置文件
一.gradle // https://mvnrepository.com/artifact/com.squareup.okhttp/okhttp compile group: 'com.square ...
- gulp#4.0
gitbook教程: https://dragon8github.gitbooks.io/gulp-webpack/content/an-zhuang-gulp-4-0.html gulpfile.j ...
- 读书笔记6pandas简单使用
一.序列Series,很像numpy中的array数组,可以由列表.元组.字典.numpy中的array来初始化 >>> from pandas import Series > ...