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();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/12929.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

iLogtail 社区开源之夏活动来了!

作者&#xff1a;玄飏 在这个充满活力的夏日&#xff0c;随着阳光一同灿烂的是开源精神的光辉与创新的火花。iLogtail 社区高兴地宣布&#xff0c;我们正式加入开源之夏 2024 的行列&#xff0c;诚邀每一位怀揣梦想与激情的学生开发者&#xff0c;共同开启一场探索技术前沿、贡…

机器学习入门介绍

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…

基于springboot+vue+Mysql的大学生社团活动平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

图文成片剪辑软件,分享3个专业的工具!

在数字化时代&#xff0c;图文成片剪辑软件成为了我们创作与表达的重要工具。无论是想要制作一段引人入胜的短视频&#xff0c;还是打造一幅精美的图文海报&#xff0c;这些软件都能助你一臂之力。那么&#xff0c;图文成片剪辑软件的方法有哪些&#xff1f;又有哪些值得一试的…

PHP开发中的不安全反序列化

序列化是开发语言中将某个对象转换为一串字节流的过程&#xff0c;转换后的字节流可以方便存储在数据库中&#xff0c;也可以方便在网络中进行传输。而反序列化则是将数据库取出的字节流或从网络上接收到的字节流反向转换为对象的过程。概念虽如此&#xff0c;但不同的开发语言…

ASP.NET在线二手交易系统的设计与实现

摘 要 随着当今社会信息技术的进步&#xff0c;基于互联网的各种应用日益受到了人们的重视&#xff0c;二手商品的重新利用也逐渐被人们关注&#xff0c;二手交易系统就在这种形势下产生了&#xff0c;它利用网络&#xff0c;改变了人们的购物方式。 本文是基于现代二手交易…

AC/DC电源模块的故障诊断与维修技巧

BOSHIDA AC/DC电源模块的故障诊断与维修技巧 AC/DC电源模块是一种常用的电力转换设备&#xff0c;用于将交流电转换为直流电供给电子设备。然而&#xff0c;由于使用环境和操作不当等原因&#xff0c;电源模块可能会出现故障。本文将介绍AC/DC电源模块的故障诊断与维修技巧。…

什么?你设计接口什么都不考虑?

如果让你设计一个接口&#xff0c;你会考虑哪些问题&#xff1f; 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空&#xff0c;入参的长度限制是多少&#xff0c;入参的格式限制&#xff0c;如邮箱格式限制 返回值是否为空&#xff0c;如果为空的时候是…

不相交集合的数据结构

一、不相交集合的操作 不相交集合的数据结构维护了一组不相交动态集的集合 &#xff0c;用集合中的某个成员作为代表标识集合。 集合在没有修改的情况下每次访问代表得到的答案是相同的&#xff0c;此外在其它一些应用中&#xff0c;可能按照规定选择集合的代表&#xff0c;例如…

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送&#xff0c;发现除了我们常用的WebSocket以外&#xff0c;其实还有一种协议也能实现H5推送&#xff0c;那就是SSE协议。 而且&#xff0c;当前主流的大模型平台&#xff0c;比如ChatGPT、通义千问、文心一言&#xff0c;对话时采用的就是SSE。 什么是SSE协议…

100m/s高速轧制钢材 八轴测径仪检测毫无压力

关键词&#xff1a;八轴测径仪,在线测径仪,钢材测径仪,高速轧制 随着技术的提升&#xff0c;钢材的生产速度越来越快&#xff0c;一些高速生产的钢材&#xff0c;生产速度甚至达到了100m/s&#xff0c;这是一个非常快的速度。 如果汽车以120公里/小时的速度行驶&#xff0c;那么…

Unity WebGL全屏显示

一、删除footer节点 二、删除最下面点击事件绑定 修改Canvas宽高 canvas.style.width "960px"; canvas.style.height "600px"; 改成 canvas.style.width document.documentElement.clientWidth"px"; canvas.style.height document.document…

行为驱动开源免费接口测试框架:karate

什么是行为驱动测试&#xff1a; 行为驱动测试&#xff08;Behavior-Driven Testing&#xff0c;简称 BDT&#xff09;是一种测试方法&#xff0c;旨在通过描述系统行为和功能来编写测试用例。BDT的重点是从用户的角度出发&#xff0c;描述系统应该如何行为&#xff0c;而不是专…

DiskANN数据布局

_mem.index.data&#xff1a;和sift_base.fbin一模一样。0-3字节是总向量数&#xff0c;4-7是每个向量的特征数。后面就是依次放置的每个向量。 _disk.index&#xff1a;是存储的图&#xff0c;但是不光包含图也包含原始向量。前4KB不知道存的是啥。从第0x1000开始存放的是原始…

国内企业更喜欢私有化部署的 6 大原因

今天在 V 站看到一篇题为《为什么国内企业会更倾向于接受私有部署而不是 SaaS&#xff1f;》的帖子&#xff0c;觉得很有启发&#xff0c;这里把网友的观点稍作整理和总结&#xff0c;分享给大家参考。 在技术日益发展的今天&#xff0c;国内企业的软件部署方式似乎呈现出与欧…

【机器学习】机器学习:人工智能中实现自动化决策与精细优化的核心驱动力

&#x1f512;文章目录: &#x1f4a5;1.概述 ❤️2.机器学习基本原理 &#x1f6e4;️2.1定义与关键概念 &#x1f6e3;️2.2 机器学习算法 ☔3.自动化决策中的机器学习应用 &#x1f6b2;4.精细优化与机器学习的结合 &#x1f44a;5.挑战与前景 &#x1f4a5;1.概述 …

基于微信小程序+JAVA Springboot 实现的【房屋租赁管理系统】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 基于微信小程序的房屋租赁管理系统 在本次项目开发中&#xff0c;我们成功构建了一款基于微信小程序的房屋租赁管理系统&#xff0c;旨在通过现代化信息技术提升房屋租赁服务的效率和质量。以下是对本项目的全面总结&#xff1a; 项目背景与目…

js之选项卡制作实例

大家好&#xff0c;今天给大家书写选项卡实例&#xff0c;话不多说&#xff0c;直接上干货 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Redis-分片集群存储及读取数据详解

文章目录 Redis分片集群是什么&#xff1f;Redis分片集群的存储及读取数据&#xff1f; 更多相关内容可查看 Redis分片集群是什么&#xff1f; Redis分片集群是一种分布式部署方式&#xff0c;通过将数据分散存储在多个Redis节点上&#xff0c;从而提高了系统的性能、扩展性和…

19个测试⽤例⽣成的AI⼯具!卷起来!

在不断发展的软件开发领域中&#xff0c;确保应⽤程序的可靠性和功能性⾄关重要。 随着软件系统复杂性的增加&#xff0c;有效测试⽅法的需求也在上升。 传统的测试⽤例⽣成⽅法通常⽆法满⾜快速开发周期和复杂代码库的需求。 随着进⼊⼈⼯智能&#xff08;AI&#xff09;时…