代理(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事件,由于调用者只能触发事件,事件只能由被调用方来调用,所以即便调用者尝试修改事件的函数列表,但真到调用时也无法改变事件的函数列表。即函数列表始终由被调用者来维护,调用者的行为被约束了!

最新文章

  1. .NET框架设计(常被忽视的C#设计技巧)
  2. Android三种播放视频的方式
  3. python对象的生命周期
  4. DIV+CSS颜色边框背景等样式
  5. 六个超大规模Hadoop(前景)
  6. 011--VS2013 C++ 斜角地图贴图
  7. qt外部数据传入实现动态的折线图绘制
  8. git 入门学习笔记
  9. 为什么要坚持用ASP.NET MVC!(②)
  10. c#中方法out参数的使用
  11. Spring MVC 项目搭建 -4- spring security-添加自定义登录页面
  12. AspNet Core Api Restful +Swagger 实现微服务之旅 (三)
  13. c#套料程序设计
  14. js 实用小技巧
  15. 2018年度 35 个最好用 Vue 开源库
  16. rocket mq知识点
  17. java 四种线程池的异同
  18. Unity项目接入应用宝SDK实现截图功能
  19. 使用Nexus搭建Maven内部服务器
  20. Charles使用方法简介

热门文章

  1. [SpriteKit] 制作瓦片地图小游戏
  2. define() vs const 该如何选择?
  3. PAT 1087 All Roads Lead to Rome
  4. jQuery+ajax中,让window.open不被拦截(转)
  5. VS2005自定义ActiveX控件在asp.net中应用方法
  6. 关于ftpshell脚本中mget中去除多余交互式提示的方法
  7. 解决svchost占用内存过高问题
  8. Verilog学习笔记
  9. Centos网络配置小工具
  10. 深入理解Docker Volume(二)