委托确实是一个有趣的结构,它允许内存中的对象进行双向对话。然而,你可能会同意,从头使用委托会有一些重复代码(定义托委,声明必要的成员变量,以及创建自定义的注册/注销方法来保护封装等)。

  除了时间之外,这样使用委托来作为应用程序的回调机制会有另一个问题是:如果我们没有反委托成员变量定义为私有的,调用者就可以直接访问委托对象。这样,调用者就可以把变量赋值为新的委托对象(实际上也就删除了当前要调用的方法列表),更糟糕的是,调用者可以直接调用委托的调用列表。为说明这个问题请看如下代码:

public class Car
{ //一个委托public delegate void Exploded(string msg);//公共的,没有辅助方法public Exploded explodedList;//触发分解的通知public void Accelerate(int delta){if(explodedList!=null)explodedList("Sorry,this car is dead..");}
}

  我们不再有使用自定义的注册方法封装的私有委托成员变量。因为这些成员确实是公共的,调用者可以直接访问explodedList成员,把这个类型重新分配给新的Exploded对象并且随时调用委托:

class Program
{static void Main(string[] args){Console.WriteLine("Agh No Encapsulation!");//创建一个CarCar myCar=new Car();//我们可以直接访问委托myCar.explodedList=new Car.Exploded(CallWhenExploded);myCar.acclerate(10);//现在可以赋值一个全新对象myCar.explodedList=new Car.Exploded(CallHereToo);myCar.acclerate(10);//调用者还可以直接调用委托myCar.explodedList.Invoke("hee,hee,hee");}static void CallWhenExploded(string msg){Console.WrtieLine(msg);}static void CallHereToo(string msg){Console.WrtieLine(msg);}
}

  公共委托成员打破了封装,不仅会导致代码难以维护和调试,还会导致应用程序安全风险!显然,我们不希望给其它应用程序必变委托指向的权力以及没有我们的许可直接调用成员的权力。

  enent关键字

  为了简化自定义方法的构建来为委托调用列表增加和删除方法,C#提供了event关键字。在编译器处理event关键字的时候,它会自动提供注册和注销的方法以及委托类型任何必要的成员变理。这些委托成员变量总是声明为私有的,因此不能直接从触发事件的对象访问它们。可以肯定的是,event关键字就像一块语法糖,只是节省了我们打字的时间。

  定义一个事件分为两个步骤。首先,我们需要定义一个委托,它包含在事件触发时将要调用的方法。其次,通过C# event关键字用相关委托声明这个事件。

  Car类型事件会取与前面的调用者(AboutToBelow和Exploded)同样的名字。事件相关联的调用者会被命名为CarEventHandler。下面是对Car类型的第一次修改:

public calss Car
{//这个委托用来与Car的事件协作public delegate void CarEventHandler(string msg);//定义每个委托类型的成员变量public event CarEventHandler Exploded;public event CarEventHandler AboutToBlow;...
}

  向调用者发送一个事件,就如通过名称和相关联委托定义的必需参数来指定事件这么简单。为确保调用者注册事件,需要在调用委托的方法之前检查这个事件是否是无效值。了解这些后,下面来看修改后的Car的Accelerate()方法:

public void Accelerate(int delta)
{//如果汽车不能用了,触发引爆事件if(carIsDead){if(Exploded!=null){Exploded("sorry,this card is dead...");}}else{currSpeed+=delta;//已经不能用了吗?if(10==maxSpeed-currSpeed&&AboutToBlow!-null_{AboutToBlow("Careful boddy! Gonna blow!");}//还好着呢if(currSpeed>=maxSpeed)carIsDead=true;elseConsole.WriteLine("CurrSpeed={0}",currSpeed);}
}

  这样,我们已经设定了Car对象发送自定事件,这不再需要定义自定义注册函数,也不需要声明托委成员变量。

  临听传入的事件

  C#事件也简化了注册调用者事件处理程序的操作。现在调用者仅需使用+= 和-=运算符即可。

class Program
{static void main(string[] args){Console.Write("####Delegates as events ####\n");Car cl=new Car("SlugBug",100,10);//注册事件处理程序cl.OnAboutToBlow +=new Car.CarEventHandler(CarIsAlmostDoomed);cl.OnAboutToBlow +=new Car.CarEventHandler(CarAboutToBlow);cl.CarEventHandler d=new Car.CarEventHandler(CarExploded);c1.Exploded +=d;Console.WriteLine("Speed up");for(int i=0;i<7;i++)cl.Accelerate(20);//从调用列表中移除CarExploded方法c1.Exploded -=d;Console.WriteLine("Speed up");for(int i=0;i<7;i++)cl.Accelerate(20);Console.ReadLine();}public static void CarAboutToBlow(string msg){ Console.WriteLine(msg);}public static void CarIsAlmostDoomed(string msg){ Console.WriteLine(msg);}public static void CarExploded(stirng msg){ Console.WriteLine(msg);}
}

转载于:https://www.cnblogs.com/longProgrammer/p/3192202.html

C# 事件(第四章)相关推荐

  1. ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl

    第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经知道了,要开发自定义的控件一般继承三个基 类:Control,WebControl,还有一个就 ...

  2. 计算机二级vf知识点总结,2015年计算机二级考试《VFP》复习重点:第四章

    第四章 Visual FoxPro 数据库及其操作 1.创建数据库 可以通过以下几种方式创建数据库: (1).在"项目管理器"中创建数据库 打开" 项目管理器" ...

  3. Android群英传笔记——第四章:ListView使用技巧

    Android群英传笔记--第四章:ListView使用技巧 近期也是比較迷茫.可是有一点点还是要坚持的,就是学习了.近期离职了,今天也是继续温习第四章ListView,也拖了事实上也挺久的了,lis ...

  4. 鸟哥的Linux私房菜(基础篇)- 第二十四章、 X Window 配置介绍

    第二十四章. X Window 配置介绍 最近升级日期:2009/08/07 在 Linux 上头的图形介面我们称之为 X Window System,简称为 X 或 X11 罗!为何称之为系统呢?这 ...

  5. Prism4文档翻译(第四章 第一部分) 转载bluesky234

    本节导读: 第四章介绍了模块化应用程序开发所必要的知识和需要注意的内容.而本部分通过讲述模块化应用程序开发所注意的必要概念,包括IModule接口,模块加载过程,模块列表,模块间通信,和依赖注入容器, ...

  6. [转]Windows Shell 编程 第十四章【来源:http://blog.csdn.net/wangqiulin123456/article/details/7988010】...

    第十四章 设计Shell集成应用 有一些工具可以使应用程序更紧密地与Shell和底层系统进行集成.也就是说,用户可以象处理系统文档和程序那样处理你的文档和程序.例如,右击文件来显示可用功能列表等.Wi ...

  7. Prism4文档翻译(第四章 第二部分)

    这一部分内容有点少呃,而且翻译难度也有一些大.接下来明天或者后天就把代码的那部分(第四章 第三部分)放上来吧,最近在弄一个设计忙的要死.另外,由于最近在公司担任了一大部分的培训任务(我感觉我就是标准的 ...

  8. 如何使用计算机改进生产线,第四章 计算机生产管理.doc

    第四章 计算机生产管理 第四章 计算机辅助生产管理 基本概念 一.生产与生产管理 (一)生产的含义 生产:生产是"投入→变换→产出"的过程.p105图4-1 例:钢的生产 投入:原 ...

  9. 计算机操作系统第四章作业

    计算机操作系统第四章作业 1.何为静态链接?静态链接时需要解决两个什么问题? 答:静态链接是指在程序运行之前,先将各自目标模块及它们所需的库函数,链接成一个完整的装入模块,以后不再拆开的链接方式. 将 ...

  10. 2020-08-21 光纤通信第四章知识点整理

    第四章 光纤通信系统 目录 4.1 模拟光纤通信 2 4.2 数字光纤通信系统和总体设计 3 4.2.1 数字光纤通信系统基本组成 3 4.2.2 数字光纤通信系统总体设计 4 4.3 数字光纤传输系 ...

最新文章

  1. 7月份没啥写的。。。
  2. 13000行代码、19大技术,这位16岁高中生用C++从头到尾构建了一个机器学习库!...
  3. Java实现的简单神经网络(基于Sigmoid激活函数)
  4. linux中tomcat修改错误日志路径
  5. 学习python第四天内容回顾
  6. 研发流程与项目管理之关系
  7. 当一个美术生开始在腾讯撸代码… |「递归」第1集
  8. altert/html打印出来的是[object Object]
  9. pytest测试框架_带你深入理解自动化测试框架Pytest的配置文件!
  10. java集成 腾讯信鸽_移动推送 腾讯信鸽集成
  11. java多线程listview_Android_listview分页加载更多
  12. laravel connector.php,如何获得laravel DB连接到PHP连接?
  13. 学3dmax赚钱吗?学3dmax工资怎么样?
  14. 微信小程序——服务器接口
  15. 所有的IT男都会蛮光头?来看看编程语言之父们的头发
  16. 如何用乐高积木式操作让 ChatGPT 变得更强大?
  17. D3D9学习笔记之基础几何体的深入应用(一)
  18. Excel编程环境搭建
  19. Android MVP 架构设计 (一)
  20. AVPlayer与AVPlayerViewController媒体播放器

热门文章

  1. xfce不小心禁用了鼠标
  2. 获取国内国外flink的mailing list技术支持
  3. Error: Could not find or load main class org.apache.tez.dag.app.DAGAppMaster
  4. Kylin启动报错hbase-common lib not found
  5. LSTM原理解读汇总
  6. Google Cloud Platform试用期变成只有一天
  7. .ipynb转化为.py文件后批量删除一大堆#In[53]
  8. 是否使用wraps的區別
  9. ubuntu下面使用clion
  10. 苹果ios鸿蒙,苹果iOS界面一直都很美,鸿蒙系统在这方面,让人担心