委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。一个委托类型是代表与特定参数列表和返回类型的方法的引用类型。实例化委托时,可以将其实例与具有兼容签名和返回类型的任何方法相关联。您可以通过委托实例调用(或调用)该方法。委托用于将方法作为参数传递给其他方法。事件处理程序只不过是通过委托调用的方法。您可以创建自定义方法,并且诸如Windows控件之类的类可以在发生特定事件时调用您的方法。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ch1 { //静态方法 public delegate void GreetingDelegate(string name);//委托 public class FirstDelegate { public static void GreetingChinese(string name) { Console.WriteLine("早上好:" + name); } public static void GreetingEnglish(string name) { Console.WriteLine("Good morning:" + name); } } public class GreetingManager { public static GreetingDelegate MakeLanguageByDelegate; public static void GreetingPeople(string name) { if (MakeLanguageByDelegate != null) { MakeLanguageByDelegate(name); } } public static event GreetingDelegate MakeLanguageByEvent;//事件,不管是不是声明为public,它总是被声明为private public static void GreetingPeopleEvent(string name) { if (MakeLanguageByEvent != null) { MakeLanguageByEvent(name); } } } //普通方法 public class FirstDelegate1 { public void GreetingChinese(string name) { Console.WriteLine("早上好:" + name); } public void GreetingEnglish(string name) { Console.WriteLine("Good morning:" + name); } } public class GreetingManager1 { public GreetingDelegate MakeLanguageByDelegate; public void GreetingPeople(string name) { if (MakeLanguageByDelegate != null) { MakeLanguageByDelegate(name); } } public event GreetingDelegate MakeLanguageByEvent; public void GreetingPeopleEvent(string name) { if (MakeLanguageByEvent != null) { MakeLanguageByEvent(name); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Ch1 { /** * Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 * 水烧开的时候通知报警器和显示器 * */ public class WaterDelegate { private int temperature = 0; public delegate void BoilHandler(int param);//声明委托 public event BoilHandler BoilEvent;//声明事件 public void BoilWater() { for (int i = 0; i <= 100; i++) { temperature = i; if (temperature >= 95) //温度大于95警告并且显示温度 { if (BoilEvent != null) //如果有对象注册 { BoilEvent(temperature); //调用所有注册方法 Console.WriteLine("-----------------"); } } } } } //报警 public class Alarm { public void MakeAlert(int temperature) { Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", temperature); } /** * .Net Framework中的委托与事件 * 委托声明原型中的Object类型的参数代表了Object,也就是监视对象,在本例中是 Heater(热水器)。回调函数(比如Alarm的MakeAlert)可以通过它访问触发事件的对象(Heater)。 * EventArgs 对象包含了Observer所感兴趣的数据,在本例中是temperature。 * */ public void MakeAlert(Object sender, BoiledEventArgs e) { Heater heater = (Heater)sender; Console.WriteLine("Alarm:{0} - {1}, 嘀嘀嘀,水已经 {2} 度了 ", heater.area, heater.type, e.temperature); } } //显示 public class Display { public static void ShowMessage(int temperature) { Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", temperature); } public static void ShowMessage(Object sender, BoiledEventArgs e) { Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature); Console.WriteLine(); } } public class Heater { private int temperature; public string area { get; set; } //添加地区 public string type { get; set; } //添加类型 public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);//委托 public event BoiledEventHandler Boiled;//事件 // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视 protected virtual void OnBoild(BoiledEventArgs e) { if (Boiled != null) //如果有对象注册 { Boiled(this, e); //调用所有注册方法 } } public void BoilWater() { for (int i = 0; i <= 100; i++) { temperature = i; if (temperature >= 95) //温度大于95警告并且显示温度 { BoiledEventArgs e = new BoiledEventArgs(temperature); OnBoild(e); } } } } // 定义BoiledEventArgs类,传递给Observer所感兴趣的信息 public class BoiledEventArgs : EventArgs { public readonly int temperature; public BoiledEventArgs(int temperature) { this.temperature = temperature; } } }
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Ch1 { class Program { static void Main(string[] args) { //------------------------静态处理方法------------------------ //GreetingManager.MakeLanguageByDelegate = FirstDelegate.GreetingEnglish; //GreetingManager.GreetingPeople("jason hua"); //GreetingManager.MakeLanguageByDelegate = FirstDelegate.GreetingChinese; //GreetingManager.GreetingPeople("杰"); //GreetingManager.MakeLanguageByEvent += FirstDelegate.GreetingEnglish; //GreetingManager.GreetingPeopleEvent("Jason Hua"); //GreetingManager.MakeLanguageByEvent += FirstDelegate.GreetingChinese; //GreetingManager.GreetingPeopleEvent("杰"); //-----------------------普通处理方法------------------------------- //FirstDelegate1 fd = new FirstDelegate1(); //GreetingManager1 gm = new GreetingManager1(); //gm.MakeLanguageByDelegate = fd.GreetingEnglish;//注册对象 //gm.GreetingPeople("jason hua"); //gm.MakeLanguageByDelegate = fd.GreetingChinese;//注册对象 //gm.GreetingPeople("杰"); //Console.WriteLine(); //gm.MakeLanguageByEvent += fd.GreetingEnglish;//注册对象 //gm.GreetingPeopleEvent("jason hua"); //gm.MakeLanguageByEvent += fd.GreetingChinese;//注册对象 //gm.GreetingPeopleEvent("杰"); //普通的项目中的例子 //WaterDelegate wd = new WaterDelegate(); //Alarm alarm = new Alarm(); //wd.BoilEvent += alarm.MakeAlert;//注册对象 //wd.BoilEvent += Display.ShowMessage;//注册静态对象 //wd.BoilWater(); //仿微软的事件与委托,项目中的小例子 Heater heater = new Heater(); Alarm alarm = new Alarm(); heater.area = "河南"; heater.type = "九阳"; heater.Boiled += alarm.MakeAlert; heater.Boiled += Display.ShowMessage; heater.BoilWater(); Console.ReadLine(); } } }
引言委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。
参看网址:http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx
其他的基础功能
5. C#中泛型的解释(object,list,var,dynamic的区别)
6. C#中委托
7. C#和.NET版本对比