C#【进阶】委托和事件
委托和事件

文章目录
- 1、委托
- 1、委托概念
- 2、基本语法
- 3、定义自定义委托
- 4、使用自定义委托
- 5、委托变量可以存储多个函数
- 6、系统定义好的委托
- 思考 怪物死亡数据更新
- 2、事件
- 1、事件概念
- 2、事件的使用
- 3、为什么有事件
- 思考 热水器
- 3、匿名函数
- 1、匿名函数概念
- 2、基本语法
- 3、使用
- 4、匿名函数的缺点
- 思考 匿名函数作为返回值
- 4、Lambad表达式
- 1、Lambad表达式概念
- 2、lambad表达式语法
- 3、使用
- 4、闭包
1、委托
1、委托概念
委托是方法的容器,表示方法的变量类型
用来存储、传递方法
委托的本质是一个类,用来定义方法的类型(返回值和参数的类型)
不同的方法必须对应和各自格式一致的委托
2、基本语法
访问修饰符 delegate 返回值 委托名(参数列表);
3、定义自定义委托
访问修饰符不写默认为public声明了一个可以用来存储无参无返回值函数的容器delegate void MyFun();//表示用来装载或传递返回值为int有一个int参数的函数委托delegate int MyFu2(int x);
4、使用自定义委托
委托变量是函数的容器委托常用在:1、作为类的成员2、作为函数的参数static void Fun(){Console.WriteLine("aaa");}//声明委托方法1、将Fun()方法存到MyFun委托容器中MyFun f = new MyFun(Fun);//方法1、调用委托f.Invoke();f();//声明委托方法2、声明委托变量f2存储Fun()方法MyFun f2 = Fun;//方法2、调用委托f2();f2.Invoke();static int Fun2(int value){return value;}MyFun2 f3 = Fun2;Console.WriteLine(f3(1));MyFun2 f4 = new MyFun2(Fun2);Console.WriteLine(f4.Invoke(3));//声明委托
delegate void MyFun();
//表示用来装载或传递返回值为int有一个int参数的函数委托
delegate int MyFun2(int x);
5、委托变量可以存储多个函数
增加函数MyFun ff = Fun;ff += Fun;ff();class test{MyFun fun;MyFun2 fun2;public void AddFun(MyFun fun, MyFun2 fun2){this.fun += fun;this.fun2 += fun2;}}
移除函数ff -= Fun;//清空ff = null;if(ff!=null){ff();}
6、系统定义好的委托
无参无返回值 // Action
Action action = Fun;
有参无返回值 // Action<>
Action<int,string> action2 = Fun;
指定返回值类型 // Func<>
Func<string> func = Fun;
有参数有返回值 //Func<参数,返回值>
Func<int,int> func = Fun;
思考 怪物死亡数据更新
//怪物死亡后,玩家要加10元钱,界面要更新数据
//成就要累加怪物击杀数,用委托实现这些功能Monster monster = new Monster();
Player player = new Player();
Panel panel = new Panel();
ChengJiu chengJiu = new ChengJiu();//委托关联
monster.deadDoSomthing += player.MonsterDeadDoSomthing;
monster.deadDoSomthing += panel.MonsterDeadDoSomthing;
monster.deadDoSomthing += chengJiu.MonsterDeadDoSomthing;
monster.Dead();class Monster
{//声明委托public Action<Monster> deadDoSomthing;public int money;public void Dead(){Random random = new Random();money = random.Next(15, 21);Console.WriteLine("怪物死亡");//使用委托 这里的this是将自己作为参数传出去if (deadDoSomthing != null) { deadDoSomthing(this); }deadDoSomthing = null;}
}
class Player
{private int myMoney = 0;public void MonsterDeadDoSomthing(Monster m){myMoney += m.money;Console.WriteLine("击杀获得{0}金币" , m.money);Console.WriteLine("余额"+myMoney);}
}
class Panel
{private int nowShowMoney = 0;public void MonsterDeadDoSomthing(Monster m){nowShowMoney += m.money;Console.WriteLine("显示余额" + nowShowMoney);}
}class ChengJiu
{private int nowKillMonsterNum = 0;public void MonsterDeadDoSomthing(Monster m){nowKillMonsterNum++;Console.WriteLine("击杀数量" + nowKillMonsterNum);}
}
2、事件
1、事件概念
事件是基于委托的存在
事件是委托的安全包裹
让委托的使用更具有安全性
事件是一种特殊的变量类型
2、事件的使用
声明语法:访问修饰符 event 委托类型 事件名;
事件的使用:1、事件是作为成员变量存在于类中2、委托怎么用,事件就怎么用
事件相对于委托的区别:1、不能在类外部赋值,但可以加减2、不能在类外部调用
注意:它只能作为成员存在于类、接口以及结构体中不能作为临时变量Test test = new Test();
class Test
{//委托成员变量,用于存储函数public Action myFunc;//事件成员变量,用于存储函数public event Action myEvent;public Test(){myFunc = TestFunc;myFunc += TestFunc;myEvent = TestFunc;myEvent += TestFunc;myEvent();myEvent.Invoke();myEvent = null;}public void TestFunc(){}
}
3、为什么有事件
1、防止外部随意置空委托
2、防止外部随意调用委托
3、事件相当于对委托进行了一次封装,让其更加安全
思考 热水器
//有一个热水器,包含一个加热器,一个报警器,一个显示器
//我们给热水通上电,当水温超过95度时
//1、报警器会开始发出语音,告诉你水温
//2、显示器也会改变水温提示,提示水已经烧开Heater h = new Heater();
Alarm alarm = new Alarm();
Display display = new Display();h.myEvent += alarm.ShowInfo;
h.myEvent += display.ShowInfo;
h.AddHot();
class Heater
{public event Action<int> myEvent;private int temperature = 25;public void AddHot(){int updateIndex= 0;while (true){if (updateIndex % 9999999 == 0){temperature++;Console.WriteLine("温度计"+temperature);if (temperature >= 95){if (myEvent!=null){myEvent(temperature);}myEvent = null;}if (temperature >=100){break;}updateIndex = 0;}updateIndex++;}}
}
class Alarm
{public void ShowInfo(int v){Console.WriteLine("滴滴,温度" + v);}
}
class Display
{public void ShowInfo(int v){Console.WriteLine("显示温度" + v);}
}
3、匿名函数
1、匿名函数概念
配合委托和事件使用
脱离委托和事件,是不会使用匿名函数的
2、基本语法
delegate(参数列表){函数逻辑};
何时使用1、函数中传递委托参数时2、委托或事件赋值时
3、使用
//1、无参无返回值
Action action = delegate ()
{Console.WriteLine("匿名函数");
};
action();
//2、有参
Action<int,string> b = delegate (int a, string b)
{Console.WriteLine(a);Console.WriteLine(b);
};
b(1,"a");
//3、有返回值
Func<string> c = delegate ()
{return "a";
};
Console.WriteLine(c());
//4、一般情况会作为函数参数传递,或者作为函数返回值
Test t = new Test();
//参数传递
t.Do(1, delegate () { Console.WriteLine("随参数传入的匿名函数逻辑"); });
//返回值
Action ac = t.GetFun();
ac();
//直接调用返回的委托函数
t.GetFun()();
class Test
{public Action action;//作为参数传递时public void Do(int a , Action fun){Console.WriteLine(a);fun();}//作为返回值public Action GetFun(){return delegate () { Console.WriteLine("函数内部返回的一个匿名函数逻辑"); };}
}
4、匿名函数的缺点
添加到委托或事件容器中后,不记录无法单独移除
思考 匿名函数作为返回值
//写一个函数传入一个整数,返回一个函数
//之后执行这个匿名函数时传入一个整数和之前那个函数传入的数相乘
//返回结果
Func<int, int> func = TestFunc(2);
Console.WriteLine(func(3));
Func<int, int> TestFunc(int i)
{//会改变i的生命周期return delegate(int v) {return i * v; };
}
4、Lambad表达式
1、Lambad表达式概念
匿名函数的简写
2、lambad表达式语法
(参数列表) =>{};
3、使用
//1、无参无返回值
Action a = () =>
{Console.WriteLine("无参无返回值");
};
a();
//2、有参无返回值
Action<int> a2 = (int value) =>
{Console.WriteLine("有参无返回值" + value);
};
a2(2);
//3、省略参数类型,参数类型和委托或事件容器一致
Action<int> a3 = (value) =>
{Console.WriteLine("省略参数写法" + value);
};
a3(3);
//有参有返回值
Func<string, int> a4 = (value) =>
{Console.WriteLine("有参有返回值lambad" + value);return 1;
};
Console.WriteLine(a4("a"));
4、闭包
内层函数可以引用包含在它外层函数的变量
即使外层函数的执行已经终止
注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值Test t = new Test();
t.DoAction();
class Test
{public event Action action;public Test(){//闭包int value =10;action = () =>{Console.WriteLine("闭包的值"+value);};for (int i = 0; i < 10; i++){//每次循环的index不一样,此非彼int index = i;action += () =>{Console.WriteLine();Console.WriteLine("假循环"+i);//最终值Console.WriteLine("真循环" + index);};}}public void DoAction(){action();}
}
相关文章:
C#【进阶】委托和事件
委托和事件 文章目录 1、委托1、委托概念2、基本语法3、定义自定义委托4、使用自定义委托5、委托变量可以存储多个函数6、系统定义好的委托思考 怪物死亡数据更新 2、事件1、事件概念2、事件的使用3、为什么有事件思考 热水器 3、匿名函数1、匿名函数概念2、基本语法3、使用4、…...
【class9】人工智能初步(处理单张图片)
Class9的任务:处理单张图像 为了更高效地学习,我们将“处理单张图像”拆分成以下几步完成: 1. 读取图像文件 2. 调用通用物体识别 3. 提取图像分类信息 4. 对应分类文件夹还未创建时,创建文件夹 5. 移动图像到对应文件夹 0.获取…...
cgicc开发 (结合jsoncpp)
#include <iostream> #include <fstream> //读写文件 c标准库 #include <string> //字符串类 c标准库 #include <sstream> //字符串流 c标准库 #include <assert.h> #include "json/json.h" //jsoncpp的头文件#include <cgicc/CgiD…...
HTML常用标签及属性
一、简单标签 标签作用div 自带换行,块级显示span 语义化标签,无任何修饰效果br 换行,单标签hr 水平分割线,单标签h1 ~ h6 标题标签,有加粗效果,h1最明显,往后依次减弱,独占一行&am…...
【PB案例学习笔记】-03用户名密码校验
写在前面 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gitee代码仓库https://gitee.com/xiezhr/pb-project-example.git 需要源代码的小伙伴们可以自行…...
设计模式六大原则之 接口分离原则
文章目录 概念比较代码示例优势 小结 概念 要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。 比较 概念有了,再来看看比较下吧,和单一职责比较比较。 接口隔离原则和单一职责都是为了提高类的…...
嵌入式学习——Shell()——day21
(1)标准IO——有缓存 1.打开文件 fopen 2.读写文件 fgetc/fputc fgets/fputs fprintf/fscanf 3.关闭文件 fclose 1. 缓存(标准I…...
STM32学习计划
前言: 这里先记录下STM32的学习计划。 2024/05/08 今天我正在学习的是正点原子的I.MX6ULL APLHA/Mini 开发板的 Linux 之ARM裸机第二期开发的视频教程,会用正点原子的I.MX6ULL开发板学习第二期ARM裸机开发的教程,然后是学习完正点原子的I.M…...
小米15曝光?可能会要稍微涨价
也许是感受到了智能机市场的逐渐复苏,最近各大手机品牌发售新品的速度明显加快了。从4月份的Redmi、一加,再到5月份一大堆vivo、OPPO新机型的发布。而近日,有关小米14即将发售的消息也是悄咪咪的放了出来。 去年发售的小米14可以说是狠狠地让…...
深度优先搜索汇总
常用英文 最近公共祖先(Lowest Common Ancestor,简称LCA) posterity,英语单词,主要用作名词,作名词时译为“子孙,后裔;后代”。 什么是深度优先搜索 深度优先搜索,D…...
【虚拟仿真】Unity3D中实现对大疆无人机遥控器手柄按键响应
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 最近项目中需要用到大疆无人机遥控器对程序中无人机进行控制,遥控器是下图这一款: 博主发…...
Python学习之路 | Python基础语法(一)
数据类型 Python3 中常见的数据类型有: Number(数字)String(字符串)bool(布尔类型)List(列表)Tuple(元组)Set(集合)Dict…...
【已解决】AttributeError: module ‘clip‘ has no attribute ‘load‘
问题描述:运行YOLO-world时出现AttributeError: module clip has no attribute load。 情况分析: 1. 未安装clip包。 2. clip包中没有load方法。 解决办法: 1.重新安装clip包。 pip install clip pip install openai-clip 2. 安装后仍然报…...
安卓实现连接wesokcet
在build.gradle里引入依赖: implementation org.java-websocket:Java-WebSocket:1.5.2 在Androidmanifest.xml 文件里加入网络权限: <uses-permission android:name"android.permission.INTERNET" /> 代码: package com.x…...
Xinstall助力App下载量精准统计,洞悉推广效果
在移动互联网时代,App的下载量是衡量一个应用受欢迎程度的重要指标。然而,要精准统计App的下载量并不是一件容易的事情。为了解决这一难题,越来越多的开发者选择了Xinstall这一专业的App全渠道统计服务商。 Xinstall作为国内领先的App统计平…...
CSS字体修饰
1)文字大小 ( font-size ) /* 设置文字大小为24个像素 */ font-size: 24px; 2)字体粗细 ( font-weight ) /* 字体粗细在100-900之间可以进行调整 */ /* 字体加粗 */ font-weight: bolder; /* 或 fon…...
高并发缓存服务的构建要点与陷阱
1. 缓存基础与特征 在讨论高并发环境下构建缓存服务的问题前,我们需要先了解缓存的基础和特征。缓存(Cache)是一种高速数据存储层,它可以存储临时数据,以便将来的请求能更快地获取到这些数据。从本质上讲,…...
Electron学习笔记(五)
文章目录 相关笔记笔记说明 七、系统1、系统对话框2、自定义窗口菜单3、系统右键菜单4、快捷键(1)、监听网页按键事件 (窗口需处于激活状态)(2)、监听全局按键事件 (窗口无需处于激活状态)(3)、补充:自定义窗口菜单快捷…...
【jest 调试 - vscode debug】
jest 测试typescript,如果想对测试文件本身断点调试。 安装jest相关依赖 # jest本体 npm install --save-dev jest # jest的类型声明 npm install --save-dev types/jest # typescript中使用 npm install --save-dev ts-jestlaunch.json 配置参考 {"type&qu…...
华为OD机试【分奖金】(java)(100分)
1、题目描述 公司老板做了一笔大生意,想要给每位员工分配一些奖金,想通过游戏的方式来决定每个人分多少钱。按照员工的工号顺序,每个人随机抽取一个数字。按照工号的顺序往后排列,遇到第一个数字比自己数字大的,那么&…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
