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.xdnf.cn/news/1424548.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C脚本实现Wincc弹窗重复调用

文章目录 前言一、步骤及解析二、运行画面演示三、总结 前言 在常见的Wincc上位机画面中&#xff0c;点击按钮或控件弹出弹窗&#xff0c;由于不同的弹窗内容不同&#xff0c;变量前缀不同&#xff0c;通常情况下一个弹窗就需要调用一个画面窗口&#xff0c;但画面窗口过多会导…

MySQL存储引擎介绍

查看MySQL数据库中创建表的信息 如上图所示&#xff0c;当我们使用命令show create table server_info\G;可以显示我们所创建的表的信息&#xff0c;只显示两个字段&#xff0c;第一个字段是Table 即是创建的表的名称&#xff0c;第二个字段是Create Table即是创建的表的字段的…

基于Pytorch深度学习神经网络MNIST手写数字识别系统源码(带界面和手写画板)

第一步&#xff1a;准备数据 mnist开源数据集 第二步&#xff1a;搭建模型 我们这里搭建了一个LeNet5网络 参考代码如下&#xff1a; import torch from torch import nnclass Reshape(nn.Module):def forward(self, x):return x.view(-1, 1, 28, 28)class LeNet5(nn.Modul…

Navicat Premium数据库新建函数报错问题

1.问题产生原因&#xff1a; (1)可能是软件 Navicat Premium 的版本不一样 (2)可能是与某些字符集不一样 2.找出解决办法&#xff1a; (1)参考对照系统自带sys数据库表的函数找出的区别&#xff08;后面遇到同样问题可以这样排查&#xff09; (2)不加 DETERMINISTIC 声明&a…

点量云流3D应用线上展厅云推流方案分享

展厅是企业对外展示宣传的窗口&#xff0c;不论企业还是政fu单位、博物馆、科技馆&#xff0c;展厅都可以给用户一个更直观的感受。而随着技术的发展&#xff0c;展厅展示的内容也从最初的图文、视频&#xff0c;扩展更多文件类型&#xff0c;比如PPT\PDF文件以及3D应用数字孪生…

字符串_字符函数和字符串函数

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。 字符串常量适用于那些对它不做修改的字符串函数。 目录 1.函数介绍 1.1strlen 1.1.1strlen函数的模拟实现 1.2strcpy 1.2.1st…

OpenAI 重磅发布GPT 4o!可以视频聊天的AI?

OpenAI 重磅发布GPT 4o&#xff01; 前言 就在今日&#xff0c;OpenAI发布了ChatGPT-4o版本&#xff0c;技术主管 Mira Murati 在直播中表示GPT-4o对比之前版本速度更快&#xff0c;在文本、视频和音频方面的能力也都有所提高。值得注意的是它还可以让用户与 ChatGPT 进行视频聊…

C++学习一(主要对cin的理解)

#include<iostream> int main() {int sum 0, value 0;//读取数据直到遇到文件尾&#xff0c;计算所有读入的值的和while (std::cin >> value){ //等价于sumsumvaluesum value;}std::cout << "Sum is :" << sum << std::endl;sum …

Java—字节码文件解读

原文 public class ClassIntrucation {public static void main(String[] args) {int i 10;int j i;j;j;} } 查看字节码文件命令 javap -c 字节码文件例如&#xff1a; javap -c ClassIntrucation 结果 public class ClassIntrucation {public ClassIntrucation();Code:…

怎么把3d模型导出cad立面---模大狮模型网

在设计工作中&#xff0c;将3D模型导出到CAD软件并生成立面图是一项常见但关键的任务。这不仅有助于更好地展示设计方案&#xff0c;还能方便后续的工程制图和施工。本文将介绍如何通过3ds Max软件将3D模型导出到CAD软件&#xff0c;并生成高质量的立面图&#xff0c;为您提供实…

英飞凌SiC模块为小米电动车提供动力

至2027年之际&#xff0c;SiC功率模块与裸片产品将荣耀登场&#xff0c;助力小米电动汽车新品SU7璀璨问世。英飞凌&#xff0c;这家业界翘楚&#xff0c;将倾其所能&#xff0c;为小米SU7 Max提供两颗HybridPACK Drive G2 CoolSiC 1200 V模块&#xff0c;如同给电动汽车的心脏注…

遇到好书不容易,《米小圈上学记》与孩子一起见之!幸之!

曾听说&#xff0c;孩子阅读的第一部长篇小说&#xff0c;将会对她的性格和心灵产生长达一生的影响&#xff1b;又听说&#xff0c;在少年养志的阶段&#xff0c;让孩子多读名人传记&#xff0c;一定能有某个人成为她的目标或者偶像。 因此&#xff0c;一直以来我都在寻找最…

亲子失和最大的内耗是:家长总是“说硬话,办软事”!

一声爸妈&#xff0c;一辈子的责任&#xff0c;操不完的心、做不完的事。 然而&#xff0c;爱太满&#xff0c;注定会溢出。爱有边界&#xff0c;我们是父母&#xff0c;更是自己&#xff01; 01 前些时候悠悠起床又开始混账了&#xff01; 气愤的是&#xff0c;周末休息那…

【强化学习】DQN类算法的一些理解

一、DQN算法为什么要使用两个网络&#xff1f; DQN算法通常包含两个网络&#xff1a;一个是评估网络training_network&#xff0c;另一个是目标网络target_network。这两个网络的结构和初始权重是相同的&#xff0c;但它们的权重是不同步更新的。使用两个网络的原因是为了稳定…

计算机的内存是如何实现的

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

xxljob分片广播+多线程实现高效定时同步elasticsearch索引库

需求&#xff1a;为了利用elasticsearch实现高效搜索&#xff0c;需要将mysql中的数据查出来&#xff0c;再定时同步到es里&#xff0c;同时在同步过程中通过分片广播多线程提高同步数据的效率。 1. 添加映射 使用kibana添加映射 PUT /app_info_article {"mappings&quo…

传输层协议——TCP协议

TCP协议又叫传输控制协议&#xff0c;TCP/IP协议是计算机通信网络中目前使用最多的协议&#xff0c;同时也融入了生活的方方面面&#xff0c;不管是浏览网页使用的http/https协议、物联网设备使用的MQTT/MQTTS协议与下载文件使用的ftp协议、工业以太网中使用的Modbus TCP协议等…

不用投稿邮箱,怎样向各大新闻媒体投稿?

身为单位的信息宣传员,我深知肩上责任重大。每个月,完成单位在媒体上投稿发表文章的考核任务,就如同一场无声的赛跑,既要保证速度,更要注重质量。起初,我遵循“前辈们”的老路,一头扎进了邮箱投稿的海洋。但很快,现实给了我一记重拳——邮箱投稿的竞争犹如千军万马过独木桥,稿件…

维护表空间中的数据文件

目录 向表空间中添加数据文件 从表空间中删除数据文件 删除users表空间中的users02.dbf数据文件 对数据文件的自动扩展设置 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 维护表空间中的数据文件主要包括向表空间中添…

单位个人怎样向报社的报纸投稿?

作为一名单位的信息宣传员,我肩负着每月定期在媒体上投稿发表文章的重任。然而,在投稿的道路上,我经历了不少波折和挫折。 一开始,我天真地以为只要将稿件发送到报社的投稿邮箱,就能轻松完成任务。然而,现实却远比我想象的复杂。邮箱投稿的竞争异常激烈,编辑们会在众多稿件中挑…