事件和委托的悲伤故事

devtools/2024/12/22 20:42:43/

小强的故事

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

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

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/devtools/119497.html

相关文章

【LeetCode周赛】第 416 场

3295. 举报垃圾信息 给你一个字符串数组 message 和一个字符串数组 bannedWords。 如果数组中 至少 存在两个单词与 bannedWords 中的任一单词 完全相同&#xff0c;则该数组被视为 垃圾信息。 如果数组 message 是垃圾信息&#xff0c;则返回 true&#xff1b;否则返回 false…

Remotion:使用前端技术开发视频

前言 最近做文章突然想到很多文章其实也可以用视频的方式来展现&#xff0c;以现在短视频的火爆程度&#xff0c;肯定能让更多的人看到。 恰巧最近看了很多关于动画的前端 js 库&#xff0c;那如果将这些动画帧连续起来&#xff0c;岂不是就成了一个视频吗&#xff1f; 而且…

Win10系统使用mstsc远程电脑的时候发现隔一段时间就无法使用剪贴板_rdpclip---Windows运维工作笔记055

最近在使用温湿系统的远程桌面功能的时候发现,每当使用一段时间的时候,这个时候远程桌面功能的粘贴板就没办法使用了。 正常情况下,不管我一个电脑远程了多少台电脑,那么这些电脑之间都是可以使用粘贴板的,可以用来从一个电脑中截了图,然后粘贴到另一个电脑中。 但是现…

深度探索与实战编码:利用Python与AWS签名机制高效接入亚马逊Product Advertising API获取商品详情

亚马逊商品详情接口技术贴及代码示例 在电商数据分析和产品管理中&#xff0c;获取商品的详细信息是至关重要的一环。亚马逊作为全球领先的电商平台&#xff0c;提供了丰富的商品数据和强大的API接口&#xff0c;使得开发者能够轻松获取商品的详细信息。本文将详细介绍如何使用…

【Golang】Go语言字符串处理库--strings

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【SQLite】sqlite | insert插入存在即更新

一、概述 需求开发有需要处理insert的场景&#xff0c;索引字段存在时&#xff0c;容易冲突&#xff1b;必要时可以进行更新 二、更新方案 1、方案一&#xff1a;insert into ...on conflict (索引字段) do update set... insert into t_device values (1, 2, 2, 2, now) on…

算法:153.寻找旋转排序数组中的最小值

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;二分&#xff09; 题目要求O(logN)的时间复杂度&#xff0c;那就必然是使用二分算法了。 怎么个二分呢&#xff1f; 首先&#xff0c;我们来寻找二段性 我们看示例一&#xff1a; 3&#xff0c;4&#xff0c;5&…

HTTPS协议详解:从原理到流程,全面解析安全传输的奥秘

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…