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;欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…

sklearn机器学习编程练习大全(一)

sklearn机器学习编程练习大全 第1题 计算DataFrame每列的缺失值比例第2题 填充缺失值第3题 使用常量填充缺失值第4题 使用最频繁出现的值填充缺失值第5题 过滤掉存在空值的行第6题 使用常量填充字符串列第7题 数值离散化第8题 虚拟编码第9题 提取元素的个数第10题 特征提取--是…

基于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;如果为空的时候是…

VC++6.0自定义实现日志记录到文件及界面显示

1&#xff0c;实现日志记录到文件&#xff0c;支持日志文件大小限制&#xff0c;节省空间 void CController::LogWriteRecord(CString strText,CString strFileName) {CStdioFile csFile;try{BOOL bRet csFile.Open(strFileName,CFile::modeCreate|CFile::modeNoTruncate|CFi…

不相交集合的数据结构

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

【CSS基础】

4.CSS基础 4.1css的介绍 层叠样式表(英文全称:Cascading Style Sheets),是一种对web文档添加样式的简单机制&#xff0c;属于表现层的布局语言.4.2css基础语法 CSS语法由两部分组成&#xff1a;选择符、声明。 声明包括&#xff1a;属性和属性值选择符 {属性: 属性值 ;属性:…

docker 配置文件使用经验,后续持续增加

1. 容器中如何访问主机服务 在docker容器、docker compose 中如何访问主机服务呢&#xff1f; docker容器 20.10.0 版本在 linux 新增 host.docker.internal 支持&#xff1a; docker run -it --add-hosthost.docker.internal:host-gateway alpine cat /etc/hosts 127.0.0.…

leetcode hot100_part28_图论

目录 200.岛屿数量 DFS bfs 并查集 994.腐烂的橘子 207.课程表 DFS BFS 208.实现Trie&#xff08;前缀树&#xff09; 做完了这四题&#xff0c;总结一下&#xff0c;还是要掌握基本的dfs&#xff0c;bfs模版&#xff0c;都是在这些基础上变换的。 模版&#xff1a; …

项目-坦克大战

增加功能 我方坦克在发射的子弹消亡后&#xff0c;才能发射新的子弹。同时实现发多颗子弹 1&#xff0c;在按下J键&#xff0c;我们判断当前hero对象的子弹&#xff0c;是否已经销毁2&#xff0c;如果没有销毁&#xff0c;就不去触发shotEnemyTank3&#xff0c;如果已经销毁&…

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

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

文件上传OSS实现

1). 定义OSS相关配置 在sky-server模块 application-dev.yml sky:alioss:endpoint: oss-cn-hangzhou.aliyuncs.comaccess-key-id: LTAI5tPeFLzsPPT8gG3LPW64access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7bucket-name: sky-take-outapplication.yml spring:profiles:a…

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;而不是专…