C#笔记4 详细解释事件及其原型、匿名方法和委托的关系

本文主要是介绍C#笔记4 详细解释事件及其原型、匿名方法和委托的关系,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

匿名方法

定义

匿名方法允许一个与委托关联的代码被内联的写入使用委托的位置。

语法形式

delegate(参数列表)
{代码块
}

前文说过,委托是定义了一个公司,公司专门承接某一类型的任务。

委托的实例化就是公司把任务交给了具体的职员(方法)。

委托可以多播,公司可以同时让两个职员来服务客户。

匿名方法就是一个临时职员,这个职员不用提前招聘,只是临时取用,所以直接出现在代码里临时定义。

//定义一个公司
delegate void Company(string task)
class program
{void wokerwy(string task){dosomething();}static void Main(string[] arg){Company newworker=delegate(string ){dosomething2();}newworker.Invoke("任务1给匿名临时员工");newworker=workerwy;newworker("wy正在工作");}
}

可以看到我们先定义了公司或者说中介的形式,具体干活或者说做事的员工*(方法)还没确定。

我们公司本身就有一个员工,可以处理该任务。还有一个匿名员工临时工,在运行时才定义,被调用。注意:invoke等于直接后面跟括号,事实上编译器在你调用委托的时候会默认调用invoke方法。


事件

事件定义

当某个类的对象在运行中遇到一些特定事件,这些事件需要通知给其他代码或者这个对象的使用者,该怎么办?

当发生某个对象相关的事件使,类要使用事件将这一对象通知给用户,这种通知就叫做引发事件。

委托的存在作为事件传递的道路。

怎么理解?

委托是一系列方法的引用,就好像一个公司或者一个工作室或者一个团队,中间干活的人(方法)可能有很多。

当我们换个方式解释,如果委托变成一个触发事件,所有订阅这个事件的人都对该事件做出反应,也就是,我们原本理解委托是从正面的客户去看的,也就是我们从客户的角度去看,是一个公司里面有很多员工,我们调用这个委托,就相当于调用了所有它引用的方法。

当我们从公司里面的角度来看,此时客户的来访(委托的调用)就像一个事件,当客户来访我们就要触发这个事件并传入参数。然后我们的各种方法都要对其做出反应。

如果把整个事情串联起来我们得到什么样的逻辑:

首先存在一类工作室类型,接收某些要求,给出某些产出。

一个用户知道一个这种工作室,能够访问这个工作室,访问会提出了需求(参数),工作室所有成员会做出相应反应。

对应:

首先申明一个委托类型,接收某些参数,返回某些数值。

一个发布者类含有这个委托的某个实例。发布者能够触发这个委托(事件),触发时会给出参数,之后委托引用的所有方法开始工作。

代码解释:

using daylife;Console.WriteLine("顾客要买什么?");customer cstm = new customer();
worker wy=new worker();
wy.onwork(cstm);
string sth=Console.ReadLine();
cstm.Someonebuysth(sth);
Console.ReadLine();//申明一种委托(专门卖货物的工作室)
public delegate void market(string goods);//日常生活
namespace daylife
{//定义一个(事件的发布者)public class customer{//定义一个公司//委托的发布public market bigmarketservice;//public void Someonebuysth(string goods){Console.WriteLine("有人购物!");if (goods != null)//检查参数是否合法{if (bigmarketservice != null) //如果委托已经订阅了方法(这个超市里有人响应){//响应,也就是调用委托对应的方法bigmarketservice(goods);}}}}public class worker{bool isworking= false;//订阅购买委托事件public void onwork(customer cstm){if(isworking == false){cstm.bigmarketservice += give;}}//定义一个方法,用来响应委托public static void give(string goods){Console.WriteLine("wy给你" + goods);}//取消订阅public void offwork(customer cstm){if (isworking == true){cstm.bigmarketservice -= give;}}}
}

可以看到我们设置了两个类,分别是客户类和工作人员类,客户类拥有对市场(委托的发布)的引用 ,我们的工作人员可以选择在市场上班(工作人员订阅这个委托,此时也可以说委托订阅了工作人员give这个方法。),然后客户访问我们的市场时就会触发市场事件,就会由当前订阅了这个事件的员工响应。

一个类中包含一个委托,这个类中包含触发这个委托的方法。这个类叫做发布者类。

其他类中包含对发布者类的订阅方法,也就是存在将自己的方法附加到发布者类委托的响应这一操作。这个类叫做订阅者类。

可以有多个订阅者类,一个订阅者类可以实例化多个订阅者。

 相信看到这,应该理解了委托是什么。就是一个类将在触发委托时调用自己乃至其他类中的方法,所有订阅了该委托(事件)的方法都会执行。

这个机制很好,委托可以发布在不同的类,不同的类都可以订阅同一个委托,可以灵活的控制要调用的方法。

事件的发布和订阅

在使用委托作为通知其他类执行对应代码时我们会发现,所有拿到这个委托引用的类都可以修改其对应的方法,这让整个结构变得不稳定,如果有一个类中代码写的是:

cstm.bigmarketservice = give;

而不是:

cstm.bigmarketservice += give;

就会导致,之前其他类的订阅失效。

这很明显是不科学的,一个类或者说一个对象应该只能取消自己对这个委托事件的订阅才对。

于是C#提供了专门的事件处理机制,保证事件订阅的可靠性,其做法是在发布的委托定义中加上event关键字,其他代码不变。

public event market bigmarketservice;

这样后面其他的类在获得引用时,只能进行+=或者-=的操作,而不能直接使用=。并且,事件即使是public的,也不能被除了发布者类以外的调用。

如此,解决了一个安全隐患,可以看出,事件就是一种特殊的委托,发布者发布了事件之后,订阅者只能进行自身的订阅或者取消。

委托事件的内置类型和windows事件

见后续。

这篇关于C#笔记4 详细解释事件及其原型、匿名方法和委托的关系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1123054

相关文章

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

如何在Mac上安装并配置JDK环境变量详细步骤

《如何在Mac上安装并配置JDK环境变量详细步骤》:本文主要介绍如何在Mac上安装并配置JDK环境变量详细步骤,包括下载JDK、安装JDK、配置环境变量、验证JDK配置以及可选地设置PowerSh... 目录步骤 1:下载JDK步骤 2:安装JDK步骤 3:配置环境变量1. 编辑~/.zshrc(对于zsh

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a