事件和委托的悲伤故事

server/2024/10/18 10:17:04/

小强的故事

从前的从前,有一个村子,叫双空函数村,各个不同的函数相互帮衬,幸福而稳定的劳作着。

虽然村子里每个函数都是空参空返回,但每个函数脑子里都装着不一样却一生注定的指令。(即程序开始编译之后)

class 双空血统()
{

public void 指令() { }//指令里的内容越多,实力越强

}

里面有一个函数叫小强   MrQiang=new 双空血统()。小强是个不走运的孩子,刚出生的时候继承了村子的双空血统,空参空返回,这倒没什么,最可怜的是,小强甚至指令都是空的。

从小到大,小强受尽了周围人的嘲笑,老函数门背后议论小强,中年函数不让孩子和小强玩

“和那个连指令没有的三空函数玩,小心变得没指令!”

小强不甘心自己一生只能执行这几条指令,于是踏上了寻求变化之法的旅途。

一年又一年,寻寻觅觅,道法却似乎总与小强无缘。小强也慢慢开始变得消沉,没盘缠了就在街边讨钱,钱够了也不继续赶路,而是在湖边喝酒。

就这样可怜的又过活了一年...

一天,小强讨够钱照常去湖边喝酒,举杯间刻,身后一只手突然停住小强的酒杯,

“孩子,我看你骨质疏松,面色憔悴,却颇有狼子之气,来,跟我学吧”

“你是?”

“老衲化名给特,你也可以叫我伟拓大师,看你也是求道之函数,教你灵活七十二变之法可好?”

小强眼睛都放亮了,当场下跪,哭着说“师傅!请教我本领!!”

经历了三年一日复一日的淬炼,小强勤学苦练,伟拓看在眼里很是欣慰。

最后,伟拓大师把自己的delegate秘法,传授给了小强,对小强说“小强,你已经是可以独当一面的函数了,和你同类型的函数里,已经不会有能在指令上战胜你的了,你可以走了”

小强没有说话,泪流满面,给伟拓大师连磕了三个头,然后踏上了返回双空村的道路。

即使在学习完这套功法之后,小强也无法斩去曾经那个空指令方法,只能以伟拓秘法为核心再造了自己的指令内核,

因为本质上,那个原方法的空指令已经是无法改变的事实。虽然当前的委托与原生的同名,但已经因为变化之法,不再固定了。

伟拓大师之秘法:public delegate void 变化之法();

class 双空血统()
{

public void 指令() { }

public 变化之法 新指令;//得到新的指令内核

}

一路上,小强也吸取(+=)了很多同血统的函数的指令,回到村子的时候,他已经是指令最多的函数了。

村中长老看到小强吸收了那么多无参无返回的指令,觉得小强使了妖术,要惩罚小强。

然而即使小强习得了delegate秘法,但新的指令内核并无稳定性,

长老们轻松施法

MrQiang.新指令=null;

把小强的所有指令清空了,并且关小强进小黑屋待了几个月。

 

小强不服,在小黑屋的几个月,他不停的思考着破局的方法,

“可恶,要怎么才能让那些老头子失去对我的指令的控制权?难道要变成private吗?可是那样我也吸取不了别人的双空指令了!师傅!我该怎么办!”。

......此时小强隐隐的感到一阵胃疼

“呓!胃疼......”

忽然之间,金光乍现,小强感受到一股前所未有的力量似乎流入了他的血液。这股力量不同于第一次习得变化之法产生的指令,而是像,得到了第二个可吸取别人的指令内核,并且和之前秘法修炼出的指令内核互相独立。

“?!!这种感觉!!”

伟拓大师之秘法:public delegate void 变化之法();

class 双空血统()
{

public void 指令() { }

public 变化之法 新指令;//只是伟拓秘法

public event 变化之法 第二新指令;//得到胃疼刺激的变化之法的再延伸

}

 两个月后,小强终于出小黑屋了,这一次,小强带着新的指令内核,为了防止再次被清空,他又离开了村子,去吸取漂泊四海的双空函数的指令。

而这一次,一过就又是三年,小强带着成吨的指令,再次回到了村子,村里的人对小强如此之多的指令再次议论纷纷,觉得小强又用了妖术,向长老告状。

而现在,长老们也无能为力了,因为小强现在的指令都在第二新指令里,已经是升级版的伟拓秘法了,外部已经不能再随意修改小强的指令了,

而唯一能再次清空小强指令的办法,只有一个一个的找到散落在天涯的被小强吸取(+=)过的双空人,从他们取消(-=)自己被吸取的部分。

故事的最后,小强因为指令数的庞大,拥有强大力量,双空村从此改名三空村

小强升职加薪,月薪过万,迎娶白富美,走上函数巅峰。

现在再看下专业一点的说明

事件委托增加了保护机制

委托明明有各种函数在里面,却灵活的像个变量,但如果不加保护,可能带来以下问题:

  1. 随意调用:类外代码可以在任何时候调用委托,这可能在错误的时间触发不应发生的行为。

    public class HealthSystem
    {public UnityAction OnHealthLow;  // 委托,可以被外部代码赋值和调用public void CheckHealth(int health){if (health < 20){OnHealthLow?.Invoke();  // 触发委托}}
    }public class Game
    {public static void Main(){HealthSystem healthSystem = new HealthSystem();// 在健康系统外部肆意玩弄里面的委托变量,里面现有的委托被任意修改healthSystem.OnHealthLow = () => { Console.WriteLine("Health is low!"); };// 正常的调用健康系统里的委托healthSystem.CheckHealth(10);  // 输出: "Health is low!"// 外部代码可以随意调用健康系统里的public委托委托像极了一个变量healthSystem.OnHealthLow();  // 输出: "Health is low!"  // 错误触发}
    }
  2. 覆盖或替换类外部代码可以替换委托的内容,导致原本绑定的回调被覆盖,影响程序的正确性和稳定性。如果程序中某个委托本应绑定特定方法,但外部代码替换了它,可能导致逻辑错误。

有了事件的保护后

public class HealthSystem
{public event UnityAction OnHealthLow;  //在前面加上event,委托就此支棱public void CheckHealth(int health){if (health < 20){OnHealthLow?.Invoke();  // 触发事件(也就是在健康系统里更硬气了的委托)}}
}public class Game
{public static void Main(){HealthSystem healthSystem = new HealthSystem();// 外部只能给事件添砖加瓦,不能动里面已有的healthSystem.OnHealthLow += () => { Console.WriteLine("Health is low!"); };// 检查健康healthSystem.CheckHealth(10);  // 输出: "Health is low!"// 不是健康系统类里的也不准调用事件// healthSystem.OnHealthLow();  // 这行代码会报错,无法直接调用}
}

事件的保护机制主要体现在以下两方面:

  1. 触发控制事件所在的类外,代码不能触发事件,只有定义事件的类内部才能触发它,确保事件只能在合适的时机执行。

  2. 防止覆盖或修改:外部代码不能直接修改或替换事件,只能订阅(+=)或取消订阅(-=),从而防止外部对事件行为的随意更改。

  3. 还有,要是+= lambda表达式这些匿名函数,就赖里面了

这两点保证了事件的安全性和可控性。

在 C# 中,如果你希望一个委托成为事件,你必须在已经声明的委托类型前面加上 event 关键字。这是将委托提升为事件的必要步骤。

委托不仅可以在类内部声明,还可以在类外部声明。

以下是unity里的GUI相关

button会触发方法,这里也是为着更好的保护委托,把委托升级成事件了,

所以在这里 public event UnityAction clickEvent;

 每个组件的都继承GUI的基类组件,如果有关事件触发,就额外增加参数,记录数值的变化


http://www.ppmy.cn/server/125276.html

相关文章

【漏洞复现】VEXUS多语言货币交易所存在未授权访问漏洞

漏洞描述 java后端,非常完整的一套交易所,UI前端做的也很漂亮,新增了交易跟单功能,前端pc+wap都是uniapp纯源码,前端源码node_modules环境已经安装好了,拿去直接编译就可以. 后端 前端 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共…

手把手教你用Python进行Web抓取(附代码)

本教程以在Fast Track上收集百强公司的数据为例&#xff0c;教你抓取网页信息。 作为一名数据科学家&#xff0c;我在工作中所做的第一件事就是网络数据采集。使用代码从网站收集数据&#xff0c;当时对我来说是一个完全陌生的概念&#xff0c;但它是最合理、最容易获取的数据来…

华为FreeBuds 6i怎么佩戴不容易掉?

华为FreeBuds 6i佩戴技巧大公开&#xff1f;给你们总结了几个佩戴更稳的小技巧&#xff0c;尊嘟很有用&#xff0c;不要再说戴不稳啦~ 1、选择大小合适的耳塞 华为FreeBuds 6i包装盒内有附赠的三种尺寸的耳塞&#xff0c;大家可以根据自己的耳道大小选择耳塞&#xff0c;试戴的…

音视频通话 SDK

腾讯云视立方音视频通话 SDK 是音视频终端 SDK&#xff08;腾讯云视立方&#xff09;的子产品 SDK 之一&#xff0c;基于音视频通话场景&#xff0c;提供专属含 UI 快速接入方案&#xff0c;仅需三步即可快速集成上线&#xff0c;轻松实现1对1视频聊天、多人视频通话和聊天应用…

HTML 盒模型

盒模型&#xff08;box model&#xff09; 简介&#xff1a;盒模型&#xff08;Box Model&#xff09;是CSS中一个非常重要的概念&#xff0c;它定义了元素在网页上的布局和尺寸。 组成&#xff1a;内容&#xff08;Content&#xff09;、内边距&#xff08;Padding&#xff…

云服务器(华为云)安装java环境。

这篇文章主要是介绍如何搭建华为云服务器中的java环境&#xff0c;也就是jdk的安装。 这里华为云服务器使用的是liunx系统。 uname -a Linux操作系统的版本信息。具体来说&#xff0c;它表明使用的是Ubuntu系统&#xff0c;内核版本是5.15.0&#xff0c;构建于2023年1月20日&a…

【重学 MySQL】四十三、多行子查询

【重学 MySQL】四十三、多行子查询 使用 IN 子查询示例&#xff1a;查找属于特定部门的员工 使用 ANY 和 ALL 子查询使用 ANY使用 ALL 注意事项 在 MySQL 中&#xff0c;多行子查询&#xff08;也称为 IN 子查询&#xff09;是指子查询返回多行数据&#xff0c;并且这些数据用于…

毕业设计选题:基于springboot+vue+uniapp的在线办公小程序

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