委托
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: "); OnBoilerEventLog("Temparature " + t + " Pressure: " + p); OnBoilerEventLog(" Message: " + 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