代理(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. 转:PHP关于反斜杠处理函数addslashes()和stripslashes()的用法

    1.php处理\函数:addslashes()和stripslashes()函数 addslashes():对输入字符串中的某些预定义字符前添加反斜杠,这样处理是为了数据库查询语句等的需要.这些预定义 ...

  2. Object-c中block需要注意的几点问题

    1. Block定义 1) 说明: a. Block是OC中的一种数据类型,在iOS开发中被广泛使用 b. ^是Block的特有标记 c. Block的实现代码包含在{}之间 d. 大多情况下,以内联 ...

  3. Linux-Linux下安装redis报错"undefined reference to__sync_add_and_fetch_4"解决办法

    如果出现这种错误可以在make的时候加上CFLAGS="-march=i686" 即 make CFLAGS="-march=i686" ----------- ...

  4. HDUOJ-----(1251)统计难题

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Subm ...

  5. iOS开发Xcode8需要注意的那些坑

    现在在苹果的官网上,我们已经可以下载到Xcode8的GM版本了,加上9.14日凌晨,苹果就要正式推出iOS10系统的推送了,在此之际,iOS10的适配已经迫在眉睫啦,不知道Xcode8 beat版本, ...

  6. GO语言学习 ---nil

    nil是什么 相信写过Golang的程序员对下面一段代码是非常非常熟悉的了: if err != nil { // do something.... }     当出现不等于nil的时候,说明出现某些 ...

  7. PLSQL_统计信息系列02_统计信息的对象

    20150505 Created By BaoXinjian

  8. PopupWindow的简单使用(结合RecyclerView)

    Android弹窗: 在Android中弹出式菜单(以下称弹窗)是使用十分广泛一种菜单呈现的方式,弹窗为用户交互提供了便利.关于弹窗的实现大致有以下两种方式AlertDialog和PopupWindo ...

  9. Linux驱动面试题总结

    1. Linux设备中字符设备与块设备有什么主要的区别?请分别列举一些实际的设备说出它们是属于哪一类设备. 字符设备:字符设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来实现这种 ...

  10. 怎样让VMware上的虚拟机ping通外网(图解教程)

    近期在实习项目中遇到一个问题. 因測试须要,本人在win7上安装VMWare后在启动两台ubuntuserver.两台主机的网络配置所有採用NAT方式实现连接. 之后一路畅通.主机ping通虚拟机和外 ...