复习委托事件
人一安逸就不思进取,找打工作后就没有以前那么认真了,人也变懒了,用不着的不学不练。想学学构架方面的知识,看着看着就发现以前不少基本的东西都生疏了。比如看到观察者模式的时候就像不太清楚委托事件的知识了,所以找了点文章复习下。
委托是一种数据结构,是一种类型,引用类型,能够引用静态方法或者实例的方法,类似于C的函数指针,可以把方法当着参数传递,在很多地方避免了进行更过的判断。
事件是实例,其实是对委托的进一步封装,其实例化了一个私有的委托对象,通过add()和remove()来注册和注销事件,以防止在实例外部能主动的触发注册的事件,而达到只能在事件的发布者内部决定是否要触发事件的目的。等于对委托的进一步阉割。
下面例子的环境是模拟用户订阅彩票发布机构,用户订阅彩票中奖号码发布机构的发布中奖号码这件事(就是订阅者对这件事情感情兴趣),当发布中奖号码事件触发,用户就能知道自己是否中奖。
彩票中奖信息发布结构。
//彩票中奖号码发布机构 public class LotteryPublisher { //声明发布中奖号码事件的委托 public delegate void PublisherHander(string _Number); //建立发布中奖号码事件 public event PublisherHander OnPublisher; //触发事件方法(发布中奖信息) public void Trigger() { string num = GetNumber(); if (OnPublisher != null) { Console.WriteLine("本期中奖号码为{0}", num); OnPublisher(num); } } //摇号(随机产生九位数字) private string GetNumber() { string num = ""; Random random = new Random(); for (int i = 0; i < 9; i++) { num += random.Next(9).ToString(); } return num; } }
购买彩票的用户。
public class Client { //客户姓名 private string name = ""; //客户自己选的号码 private string myNumber = ""; public Client(string number,string name) { this.myNumber = number; this.name = name; } //要注册的方法,查看自己是否中奖 public void Check(string number) { if (myNumber == number) { Console.WriteLine("{0}:哦也,我中奖了,哈哈哈!!!",name); } else { Console.WriteLine("{0}:TMD小日本,又没中~~~",name); } } }
接下来摇奖开始。
class Program { static void Main(string[] args) { LotteryPublisher pub = new LotteryPublisher();//实例化彩票摇奖器对象 Client client1 = new Client("9657412355","张三"); Client client2 = new Client("8516541558","李四"); pub.OnPublisher += new LotteryPublisher.PublisherHander(client1.Check); pub.OnPublisher += new LotteryPublisher.PublisherHander(client2.Check); //摇奖开始 Console.WriteLine("摇奖开始"); pub.Trigger(); Console.ReadKey(); } }
平时我们在网页上或者WinForm窗体上拖上一个button,然后双击,就能生成这样一段代码
private void button1_Click(object sender, EventArgs e) { //自定义的事件处理代码 }
我们可以看到其中有两个参数,分别是 sender和e,如果加个断点就能发现sernder就是触发事件的对象,这里也就那个button,而e就是事件感兴趣的对象,这里就是button的X,Y坐标之类的。接下来说下微软对委托事件的.Net Framework的编码规范。
1、委托类型的名称都应该以EventHandler结束。
2、委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
3、事件的命名为 委托去掉 EventHandler之后剩余的部分。
4、继承自EventArgs的类型应该以EventArgs结尾。
我们现在按照微软的编码规范再改造下我们的程序
订阅者所感兴趣的事情(摇奖产生的中奖号码)
//订阅者所感兴趣的事情(摇奖产生的中奖号码) public class NumberEventArgs : EventArgs { //摇奖产生的中奖号码 private string number; public string Number { get { return number; } set { number = value; } } public NumberEventArgs(string _number) { Number = _number; } }
彩票中奖号码发布机构。
public class LotteryPublisher { //声明发布中奖号码事件的委托 public delegate void PublisherEventHander(object sender,NumberEventArgs e); //建立发布中奖号码事件 public event PublisherEventHander Publisher; //触发事件方法(发布中奖信息) protected void OnPublisher(NumberEventArgs e) { if (Publisher != null) { Console.WriteLine("本期中奖号码为{0}", e.Number); Publisher(this,e ); } } public void Trigger() { OnPublisher(new NumberEventArgs(GetNumber())); } //摇号(随机产生九位数字) private string GetNumber() { string num = ""; Random random = new Random(); for (int i = 0; i < 9; i++) { num += random.Next(9).ToString(); } return num; } }
购买彩票客户。
//购买彩票客户 public class Client { //客户姓名 private string name = ""; //客户自己选的号码 private string myNumber = ""; public Client(string number, string name) { this.myNumber = number; this.name = name; } //要注册的方法,查看自己是否中奖 public void Check(object sender, NumberEventArgs e) { if (myNumber == e.Number) { Console.WriteLine("{0}:哦也,我中奖了,哈哈哈!!!", name); } else { Console.WriteLine("{0}:又没中~~~", name); } } }
最后开始摇奖。
static void Main(string[] args) { LotteryPublisher pub = new LotteryPublisher();//实例化彩票摇奖器对象 Client client1 = new Client("9657412355","张三"); Client client2 = new Client("8516541558","李四"); pub.Publisher += new LotteryPublisher.PublisherEventHander(client1.Check); pub.Publisher += new LotteryPublisher.PublisherEventHander(client2.Check); //摇奖开始 Console.WriteLine("摇奖开始"); pub.Trigger(); Console.ReadKey(); }
有了委托机制我们就能把方法当成参数来传递,而委托和事件结合,我们就能再出事件发布者内部定义好特定的逻辑,而在这逻辑中细节实现依赖于事件订阅者的处理逻辑,当我们把事件订阅者处理逻辑的方法以注册事件的方法(就是传递方法的委托)传递到事件订阅者内部,就能实现我们的整个功能。
现在看看上面的代码有没有一种很熟悉的感觉~~,其实.net中委托事件是对观察者模式的一种原生支持,其背后就是观察者模式(Observer)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库