C#事件和委托(C#学习笔记03)
委托
1. c# 中的委托类似于 c 或 c++ 中指向函数的指针。委托表示引用某个方法的引用类型变量,运行时可以更改引用对象。
2. 特别地,委托可以用于处理事件或回调函数。并且,所有的委托类都是从 system.delegate 类继承而来。
声明委托的语法规则:(被委托所引用的方法需有相同的参数和返回值)
delegate <return type> <delegate-name> <parameter list>
一个委托使用示例:
using system; public delegate void mydelegate(string str); //创建委托实例 namespace delegate { class textmethods { public static void method1(string str) { console.writeline("这是方法1,{0}",str); } public static void method2(string str) { console.writeline("这是方法2,{0}",str); } public static void method3(string str) { console.writeline("这是方法3,{0}", str); } } class program { static void main(string[] args) { mydelegate d1, d2, d3; //定义委托变量 d1 = textmethods.method1; d2 = textmethods.method2; d3 = textmethods.method3; d1("1"); //调用委托实例 d2("2"); d3("3"); console.writeline(""); mydelegate d4; d4 = textmethods.method1; d4 += textmethods.method2; //添加实例 d4 += textmethods.method3; d4("4"); console.writeline(""); d4 -= textmethods.method3; //移除实例 d4("5"); console.writeline(""); } } }
事件
事件是应用程序在执行过程中所关注的一些动作,但这些动作发生时,程序需要对其做出响应。事件的概念比较广泛,所有程序需要进行响应处理的动作都可以称为事件。如鼠标单击、键盘输入、计时器消息...
事件基于委托,为委托提供了一种发布/订阅机制,在.net架构内外都可以看到事件。在windows应用程序中,button类提供了click事件。这类事件就是委托,触发click事件调用的处理程序需要得到定义,而其参数由委托类型定义。
事件机制是以消息为基础的,当特定的动作发生后会产生相应的消息,关注该事件的应用程序收到事件发生的消息,就会开始指定处理过程。
示例:
参考自:[w3cschool] https://www.w3cschool.cn/wkcsharp/yvoj1nvx.html"%3ehttps://www.w3cschool.cn/wkcsharp/yvoj1nvx.html%3c/a%3e
该示例为一个简单的应用程序,该程序用于热水锅炉系统故障排除。当维修工程师检查锅炉时,锅炉的温度、压力以及工程师所写的备注都会被自动记录到一个日志文件中。
示例中可以看出,在主函数中,创建了事件发布器类(delegateboilerevent),并将一个写入文档的(订阅器)和一个控制台输出函数添加进事件示例中。在执行触发器类中的记录过程函数(logprocess() )时,就会调用所有添加进事件的函数实例。
using system; using system.io; namespace boilereventappl { // boiler 类 class boiler { private int temp; //锅炉温度 private int pressure; //锅炉压力 public boiler(int t, int p) //构造函数 { temp = t; pressure = p; } public int gettemp() { return temp; } public int getpressure() { return pressure; } } // 事件发布器 class delegateboilerevent { public delegate void boilerloghandler(string status); //声明委托 // 基于上述委托定义事件 public event boilerloghandler boilereventlog; public void logprocess() //记录过程 { string remarks = "o. k"; boiler b = new boiler(100, 12); int t = b.gettemp(); int p = b.getpressure(); if (t > 150 || t < 80 || p < 12 || p > 15) { remarks = "need maintenance"; } onboilereventlog("logging info:\n"); onboilereventlog("temparature " + t + "\npressure: " + p); onboilereventlog("\nmessage: " + remarks); } protected void onboilereventlog(string message) //函数在发布器类中,当要进行发布时,就触发事件boilereventlog所添加的实例 { if (boilereventlog != null) { boilereventlog(message); } } } // 该类保留写入日志文件的条款 class boilerinfologger { filestream fs; streamwriter sw; public boilerinfologger(string filename) { fs = new filestream(filename, filemode.append, fileaccess.write); sw = new streamwriter(fs); } public void logger(string info) //信息写入文档 { sw.writeline(info); } public void close() { sw.close(); fs.close(); } } // 事件订阅器 public class recordboilerinfo { static void logger(string info) //控制台输出信息 { console.writeline(info); }//end of logger static void main(string[] args) { boilerinfologger filelog = new boilerinfologger("boiler.txt"); //打开日志文件 delegateboilerevent boilerevent = new delegateboilerevent(); //实例化delegateboilerevent类,事件发布器 boilerevent.boilereventlog += new delegateboilerevent.boilerloghandler(logger); //boilerevent.boilereventlog为委托的实例,将logger添加进委托 boilerevent.boilereventlog += new delegateboilerevent.boilerloghandler(filelog.logger); //filelog是boilerinfologger类的实例化,将其中的logger函数添加进委托 boilerevent.logprocess(); //执行logproccess函数 filelog.close(); }//end of main }//end of recordboilerinfo }
执行结果:
logging info: temparature 100 pressure: 12 message: o. k