代理(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. MyEclipse上的第一个java web

    简单解说怎样MyEclipse上开发一个web project 以及怎样部署的问题. 第一步: 创建一个web project File -> New -> Web Project 将出现 ...

  2. 打开Activity时,不自动显示(弹出)虚拟键盘

    打开Activity时,不自动显示(弹出)虚拟键盘 在AndroidManifest.xml文件中<activity>标签中添加属性 android:windowSoftInputMode ...

  3. idea搭建简易ssm项目

    按照http://www.cnblogs.com/hackyo/p/6646051.html来搭建ssm框架,一步成功,特此记录一下. 本机环境: idea2017.3 jdk1.8 mysql5.5 ...

  4. 如何在网上隐藏自己的IP地址(转)

    摘自:http://net.yesky.com/396/3082396.shtml 在某些场合(例如论坛发贴时)有些网友希望能隐藏自己的IP地址,以免IP被记下,为安全起见,QQ聊天时也不希望别人知道 ...

  5. HDUOJ---3371Connect the Cities

    Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  6. C#中Windows Media Player控件使用实例|方法

    Windows Media Player控件Windows Media Player是一种媒体播放器,可以播放当前最流行的音频.视频文件和大多数混合型的多媒体文件.为了便于程序的开发,Visual S ...

  7. Jmeter——BeanShell PreProcessor的用法

    一.什么是BeanShell BeanShell是一个小型嵌入式Java源代码解释器,具有对象脚本语言特性,能够动态地执行标准JAVA语法,并利用在JavaScript和Perl中常见的的松散类型.命 ...

  8. 查看python selenium 的api

    DOS窗口输入: python -m pydoc -p 4567 python -m pydoc : 打开pydoc模块,pydoc是查看python文档的首选工具 -p 4567: 在4567端口启 ...

  9. 转 web前端性能分析--实践篇

    当我们知道了web前端性能的关键点后,那么接下来要做的就是如何去具体实施并获取这些关键点的数据了.通过前面的学习知道了不少好的工具,经过对比后个人觉得dynatrace还是不错的. 不仅支持ie,ff ...

  10. struts2每次访问都会创建一个新的session

    1.第一次 项目在测试过程中,突然发现登陆之后再去访问其他菜单时都会提示未登录: 查看日志之后发现是因为很多次请求时都会自动创建一个新的session,这就费解了, 因为之前也没改动什么session ...