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

相关文章

mss32.dll文件丢失怎么办? 电脑提示mss32.dll丢失的多种修复方法

《mss32.dll文件丢失怎么办?电脑提示mss32.dll丢失的多种修复方法》最近,很多电脑用户可能遇到了mss32.dll文件丢失的问题,导致一些应用程序无法正常启动,那么,如何修复这个问题呢... 在电脑常年累月的使用过程中,偶尔会遇到一些问题令人头疼。像是某个程序尝试运行时,系统突然弹出一个错误提

电脑提示找不到openal32.dll文件怎么办? openal32.dll丢失完美修复方法

《电脑提示找不到openal32.dll文件怎么办?openal32.dll丢失完美修复方法》openal32.dll是一种重要的系统文件,当它丢失时,会给我们的电脑带来很大的困扰,很多人都曾经遇到... 在使用电脑过程中,我们常常会遇到一些.dll文件丢失的问题,而openal32.dll的丢失是其中比较

python中字符串拼接的几种方法及优缺点对比详解

《python中字符串拼接的几种方法及优缺点对比详解》在Python中,字符串拼接是常见的操作,Python提供了多种方法来拼接字符串,每种方法有其优缺点和适用场景,以下是几种常见的字符串拼接方法,需... 目录1. 使用 + 运算符示例:优缺点:2. 使用&nbsjsp;join() 方法示例:优缺点:3

Mysql中深分页的五种常用方法整理

《Mysql中深分页的五种常用方法整理》在数据量非常大的情况下,深分页查询则变得很常见,这篇文章为大家整理了5个常用的方法,文中的示例代码讲解详细,大家可以根据自己的需求进行选择... 目录方案一:延迟关联 (Deferred Join)方案二:有序唯一键分页 (Cursor-based Paginatio

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

MySQL中慢SQL优化方法的完整指南

《MySQL中慢SQL优化方法的完整指南》当数据库响应时间超过500ms时,系统将面临三大灾难链式反应,所以本文将为大家介绍一下MySQL中慢SQL优化的常用方法,有需要的小伙伴可以了解下... 目录一、慢SQL的致命影响二、精准定位问题SQL1. 启用慢查询日志2. 诊断黄金三件套三、六大核心优化方案方案

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa